[dev.link] all: merge branch 'master' into dev.link

Change-Id: I446db56b20ef2189e23e225a91a17736c1d11e4c
diff --git a/src/cmd/asm/internal/flags/flags.go b/src/cmd/asm/internal/flags/flags.go
index e8535ae..1df9df9 100644
--- a/src/cmd/asm/internal/flags/flags.go
+++ b/src/cmd/asm/internal/flags/flags.go
@@ -25,8 +25,6 @@
 	SymABIs    = flag.Bool("gensymabis", false, "write symbol ABI information to output file, don't assemble")
 	Importpath = flag.String("p", "", "set expected package import to path")
 	Spectre    = flag.String("spectre", "", "enable spectre mitigations in `list` (all, ret)")
-
-	Go115Newobj = flag.Bool("go115newobj", true, "use new object file format")
 )
 
 var (
diff --git a/src/cmd/asm/main.go b/src/cmd/asm/main.go
index 9ca9797..31d8549 100644
--- a/src/cmd/asm/main.go
+++ b/src/cmd/asm/main.go
@@ -40,7 +40,6 @@
 	}
 	ctxt.Flag_dynlink = *flags.Dynlink
 	ctxt.Flag_shared = *flags.Shared || *flags.Dynlink
-	ctxt.Flag_go115newobj = *flags.Go115Newobj
 	ctxt.IsAsm = true
 	switch *flags.Spectre {
 	default:
@@ -97,8 +96,8 @@
 		}
 	}
 	if ok && !*flags.SymABIs {
-		ctxt.NumberSyms(true)
-		obj.WriteObjFile(ctxt, buf, "")
+		ctxt.NumberSyms()
+		obj.WriteObjFile(ctxt, buf, *flags.Importpath)
 	}
 	if !ok || diag {
 		if failedFile != "" {
diff --git a/src/cmd/compile/internal/gc/iexport.go b/src/cmd/compile/internal/gc/iexport.go
index 35b8d98..328260f 100644
--- a/src/cmd/compile/internal/gc/iexport.go
+++ b/src/cmd/compile/internal/gc/iexport.go
@@ -207,6 +207,7 @@
 	"cmd/compile/internal/types"
 	"cmd/internal/goobj2"
 	"cmd/internal/src"
+	"crypto/md5"
 	"encoding/binary"
 	"fmt"
 	"io"
@@ -295,12 +296,15 @@
 	hdr.uint64(dataLen)
 
 	// Flush output.
-	io.Copy(out, &hdr)
-	io.Copy(out, &p.strings)
-	io.Copy(out, &p.data0)
+	h := md5.New()
+	wr := io.MultiWriter(out, h)
+	io.Copy(wr, &hdr)
+	io.Copy(wr, &p.strings)
+	io.Copy(wr, &p.data0)
 
 	// Add fingerprint (used by linker object file).
 	// Attach this to the end, so tools (e.g. gcimporter) don't care.
+	copy(Ctxt.Fingerprint[:], h.Sum(nil)[:])
 	out.Write(Ctxt.Fingerprint[:])
 }
 
@@ -997,18 +1001,16 @@
 }
 
 func (w *exportWriter) symIdx(s *types.Sym) {
-	if Ctxt.Flag_go115newobj {
-		lsym := s.Linksym()
-		if lsym.PkgIdx > goobj2.PkgIdxSelf || (lsym.PkgIdx == goobj2.PkgIdxInvalid && !lsym.Indexed()) || s.Linkname != "" {
-			// Don't export index for non-package symbols, linkname'd symbols,
-			// and symbols without an index. They can only be referenced by
-			// name.
-			w.int64(-1)
-		} else {
-			// For a defined symbol, export its index.
-			// For re-exporting an imported symbol, pass its index through.
-			w.int64(int64(lsym.SymIdx))
-		}
+	lsym := s.Linksym()
+	if lsym.PkgIdx > goobj2.PkgIdxSelf || (lsym.PkgIdx == goobj2.PkgIdxInvalid && !lsym.Indexed()) || s.Linkname != "" {
+		// Don't export index for non-package symbols, linkname'd symbols,
+		// and symbols without an index. They can only be referenced by
+		// name.
+		w.int64(-1)
+	} else {
+		// For a defined symbol, export its index.
+		// For re-exporting an imported symbol, pass its index through.
+		w.int64(int64(lsym.SymIdx))
 	}
 }
 
diff --git a/src/cmd/compile/internal/gc/iimport.go b/src/cmd/compile/internal/gc/iimport.go
index 104b5fb..15a660c 100644
--- a/src/cmd/compile/internal/gc/iimport.go
+++ b/src/cmd/compile/internal/gc/iimport.go
@@ -697,16 +697,14 @@
 }
 
 func (r *importReader) symIdx(s *types.Sym) {
-	if Ctxt.Flag_go115newobj {
-		lsym := s.Linksym()
-		idx := int32(r.int64())
-		if idx != -1 {
-			if s.Linkname != "" {
-				Fatalf("bad index for linknamed symbol: %v %d\n", lsym, idx)
-			}
-			lsym.SymIdx = idx
-			lsym.Set(obj.AttrIndexed, true)
+	lsym := s.Linksym()
+	idx := int32(r.int64())
+	if idx != -1 {
+		if s.Linkname != "" {
+			Fatalf("bad index for linknamed symbol: %v %d\n", lsym, idx)
 		}
+		lsym.SymIdx = idx
+		lsym.Set(obj.AttrIndexed, true)
 	}
 }
 
diff --git a/src/cmd/compile/internal/gc/main.go b/src/cmd/compile/internal/gc/main.go
index 756cdbd..6e204f4 100644
--- a/src/cmd/compile/internal/gc/main.go
+++ b/src/cmd/compile/internal/gc/main.go
@@ -281,7 +281,6 @@
 	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_go115newobj, "go115newobj", true, "use new object file format")
 	flag.StringVar(&jsonLogOpt, "json", "", "version,destination for JSON compiler/optimizer logging")
 
 	objabi.Flagparse(usage)
@@ -315,7 +314,7 @@
 	// 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", "spectre", "go115newobj")
+	recordFlags("B", "N", "l", "msan", "race", "shared", "dynlink", "dwarflocationlists", "dwarfbasentries", "smallframes", "spectre")
 
 	if smallFrames {
 		maxStackVarSize = 128 * 1024
@@ -790,7 +789,7 @@
 	// Write object data to disk.
 	timings.Start("be", "dumpobj")
 	dumpdata()
-	Ctxt.NumberSyms(false)
+	Ctxt.NumberSyms()
 	dumpobj()
 	if asmhdr != "" {
 		dumpasmhdr()
@@ -1489,7 +1488,7 @@
 		return
 	}
 	s := Ctxt.Lookup(dwarf.CUInfoPrefix + "producer." + myimportpath)
-	s.Type = objabi.SDWARFINFO
+	s.Type = objabi.SDWARFCUINFO
 	// Sometimes (for example when building tests) we can link
 	// together two package main archives. So allow dups.
 	s.Set(obj.AttrDuplicateOK, true)
@@ -1501,7 +1500,7 @@
 // compiled, so that the linker can save it in the compile unit's DIE.
 func recordPackageName() {
 	s := Ctxt.Lookup(dwarf.CUInfoPrefix + "packagename." + myimportpath)
-	s.Type = objabi.SDWARFINFO
+	s.Type = objabi.SDWARFCUINFO
 	// Sometimes (for example when building tests) we can link
 	// together two package main archives. So allow dups.
 	s.Set(obj.AttrDuplicateOK, true)
diff --git a/src/cmd/compile/internal/gc/pgen.go b/src/cmd/compile/internal/gc/pgen.go
index 74654c8..f80d0c1 100644
--- a/src/cmd/compile/internal/gc/pgen.go
+++ b/src/cmd/compile/internal/gc/pgen.go
@@ -428,9 +428,10 @@
 
 	decls, dwarfVars := createDwarfVars(fnsym, fn.Func, apdecls)
 
-	// For each type referenced by the functions auto vars, attach a
-	// dummy relocation to the function symbol to insure that the type
-	// included in DWARF processing during linking.
+	// For each type referenced by the functions auto vars but not
+	// already referenced by a dwarf var, attach a dummy relocation to
+	// the function symbol to insure that the type included in DWARF
+	// processing during linking.
 	typesyms := []*obj.LSym{}
 	for t, _ := range fnsym.Func.Autot {
 		typesyms = append(typesyms, t)
@@ -480,7 +481,7 @@
 
 // createSimpleVars creates a DWARF entry for every variable declared in the
 // function, claiming that they are permanently on the stack.
-func createSimpleVars(apDecls []*Node) ([]*Node, []*dwarf.Var, map[*Node]bool) {
+func createSimpleVars(fnsym *obj.LSym, apDecls []*Node) ([]*Node, []*dwarf.Var, map[*Node]bool) {
 	var vars []*dwarf.Var
 	var decls []*Node
 	selected := make(map[*Node]bool)
@@ -490,13 +491,13 @@
 		}
 
 		decls = append(decls, n)
-		vars = append(vars, createSimpleVar(n))
+		vars = append(vars, createSimpleVar(fnsym, n))
 		selected[n] = true
 	}
 	return decls, vars, selected
 }
 
-func createSimpleVar(n *Node) *dwarf.Var {
+func createSimpleVar(fnsym *obj.LSym, n *Node) *dwarf.Var {
 	var abbrev int
 	offs := n.Xoffset
 
@@ -519,6 +520,7 @@
 	}
 
 	typename := dwarf.InfoPrefix + typesymname(n.Type)
+	delete(fnsym.Func.Autot, ngotype(n).Linksym())
 	inlIndex := 0
 	if genDwarfInline > 1 {
 		if n.Name.InlFormal() || n.Name.InlLocal() {
@@ -546,7 +548,7 @@
 
 // createComplexVars creates recomposed DWARF vars with location lists,
 // suitable for describing optimized code.
-func createComplexVars(fn *Func) ([]*Node, []*dwarf.Var, map[*Node]bool) {
+func createComplexVars(fnsym *obj.LSym, fn *Func) ([]*Node, []*dwarf.Var, map[*Node]bool) {
 	debugInfo := fn.DebugInfo
 
 	// Produce a DWARF variable entry for each user variable.
@@ -561,7 +563,7 @@
 			ssaVars[debugInfo.Slots[slot].N.(*Node)] = true
 		}
 
-		if dvar := createComplexVar(fn, ssa.VarID(varID)); dvar != nil {
+		if dvar := createComplexVar(fnsym, fn, ssa.VarID(varID)); dvar != nil {
 			decls = append(decls, n)
 			vars = append(vars, dvar)
 		}
@@ -578,9 +580,9 @@
 	var decls []*Node
 	var selected map[*Node]bool
 	if Ctxt.Flag_locationlists && Ctxt.Flag_optimize && fn.DebugInfo != nil {
-		decls, vars, selected = createComplexVars(fn)
+		decls, vars, selected = createComplexVars(fnsym, fn)
 	} else {
-		decls, vars, selected = createSimpleVars(apDecls)
+		decls, vars, selected = createSimpleVars(fnsym, apDecls)
 	}
 
 	dcl := apDecls
@@ -616,7 +618,7 @@
 			// Args not of SSA-able type are treated here; they
 			// are homed on the stack in a single place for the
 			// entire call.
-			vars = append(vars, createSimpleVar(n))
+			vars = append(vars, createSimpleVar(fnsym, n))
 			decls = append(decls, n)
 			continue
 		}
@@ -712,7 +714,7 @@
 }
 
 // createComplexVar builds a single DWARF variable entry and location list.
-func createComplexVar(fn *Func, varID ssa.VarID) *dwarf.Var {
+func createComplexVar(fnsym *obj.LSym, fn *Func, varID ssa.VarID) *dwarf.Var {
 	debug := fn.DebugInfo
 	n := debug.Vars[varID].(*Node)
 
@@ -727,6 +729,7 @@
 	}
 
 	gotype := ngotype(n).Linksym()
+	delete(fnsym.Func.Autot, gotype)
 	typename := dwarf.InfoPrefix + gotype.Name[len("type."):]
 	inlIndex := 0
 	if genDwarfInline > 1 {
diff --git a/src/cmd/internal/dwarf/dwarf.go b/src/cmd/internal/dwarf/dwarf.go
index a17b574..6ab8363 100644
--- a/src/cmd/internal/dwarf/dwarf.go
+++ b/src/cmd/internal/dwarf/dwarf.go
@@ -18,21 +18,9 @@
 	"strings"
 )
 
-// TODO(go115newobj): clean up. Some constant prefixes here are no longer
-// needed in the new object files.
-
 // InfoPrefix is the prefix for all the symbols containing DWARF info entries.
 const InfoPrefix = "go.info."
 
-// RangePrefix is the prefix for all the symbols containing DWARF location lists.
-const LocPrefix = "go.loc."
-
-// RangePrefix is the prefix for all the symbols containing DWARF range lists.
-const RangePrefix = "go.range."
-
-// DebugLinesPrefix is the prefix for all the symbols containing DWARF debug_line information from the compiler.
-const DebugLinesPrefix = "go.debuglines."
-
 // ConstInfoPrefix is the prefix for all symbols containing DWARF info
 // entries that contain constants.
 const ConstInfoPrefix = "go.constinfo."
@@ -398,9 +386,9 @@
 
 // Abbrevs() returns the finalized abbrev array for the platform,
 // expanding any DW_FORM pseudo-ops to real values.
-func Abbrevs() [DW_NABRV]dwAbbrev {
+func Abbrevs() []dwAbbrev {
 	if abbrevsFinalized {
-		return abbrevs
+		return abbrevs[:]
 	}
 	for i := 1; i < DW_NABRV; i++ {
 		for j := 0; j < len(abbrevs[i].attr); j++ {
@@ -408,7 +396,7 @@
 		}
 	}
 	abbrevsFinalized = true
-	return abbrevs
+	return abbrevs[:]
 }
 
 // abbrevs is a raw table of abbrev entries; it needs to be post-processed
diff --git a/src/cmd/internal/goobj/readnew.go b/src/cmd/internal/goobj/readnew.go
index 7a84b91..cd1a904 100644
--- a/src/cmd/internal/goobj/readnew.go
+++ b/src/cmd/internal/goobj/readnew.go
@@ -48,7 +48,7 @@
 	}
 
 	resolveSymRef := func(s goobj2.SymRef) SymID {
-		var i int
+		var i uint32
 		switch p := s.PkgIdx; p {
 		case goobj2.PkgIdxInvalid:
 			if s.SymIdx != 0 {
@@ -56,12 +56,12 @@
 			}
 			return SymID{}
 		case goobj2.PkgIdxNone:
-			i = int(s.SymIdx) + rr.NSym()
+			i = s.SymIdx + uint32(rr.NSym())
 		case goobj2.PkgIdxBuiltin:
 			name, abi := goobj2.BuiltinName(int(s.SymIdx))
 			return SymID{name, int64(abi)}
 		case goobj2.PkgIdxSelf:
-			i = int(s.SymIdx)
+			i = s.SymIdx
 		default:
 			return SymID{refNames[s], 0}
 		}
@@ -73,9 +73,9 @@
 
 	// Symbols
 	pcdataBase := start + rr.PcdataBase()
-	n := rr.NSym() + rr.NNonpkgdef() + rr.NNonpkgref()
-	ndef := rr.NSym() + rr.NNonpkgdef()
-	for i := 0; i < n; i++ {
+	n := uint32(rr.NSym() + rr.NNonpkgdef() + rr.NNonpkgref())
+	ndef := uint32(rr.NSym() + rr.NNonpkgdef())
+	for i := uint32(0); i < n; i++ {
 		osym := rr.Sym(i)
 		if osym.Name(rr) == "" {
 			continue // not a real symbol
@@ -119,7 +119,7 @@
 		}
 
 		// Aux symbol info
-		isym := -1
+		isym := ^uint32(0)
 		funcdata := make([]goobj2.SymRef, 0, 4)
 		auxs := rr.Auxs(i)
 		for j := range auxs {
@@ -131,7 +131,7 @@
 				if a.Sym().PkgIdx != goobj2.PkgIdxSelf {
 					panic("funcinfo symbol not defined in current package")
 				}
-				isym = int(a.Sym().SymIdx)
+				isym = a.Sym().SymIdx
 			case goobj2.AuxFuncdata:
 				funcdata = append(funcdata, a.Sym())
 			case goobj2.AuxDwarfInfo, goobj2.AuxDwarfLoc, goobj2.AuxDwarfRanges, goobj2.AuxDwarfLines:
@@ -142,7 +142,7 @@
 		}
 
 		// Symbol Info
-		if isym == -1 {
+		if isym == ^uint32(0) {
 			continue
 		}
 		b := rr.BytesAt(rr.DataOff(isym), rr.DataSize(isym))
diff --git a/src/cmd/internal/goobj2/objfile.go b/src/cmd/internal/goobj2/objfile.go
index 7f728e4..3e6375b 100644
--- a/src/cmd/internal/goobj2/objfile.go
+++ b/src/cmd/internal/goobj2/objfile.go
@@ -238,7 +238,8 @@
 const SymABIstatic = ^uint16(0)
 
 const (
-	ObjFlagShared = 1 << iota
+	ObjFlagShared            = 1 << iota // this object is built with -shared
+	ObjFlagNeedNameExpansion             // the linker needs to expand `"".` to package path in symbol names
 )
 
 const (
@@ -619,83 +620,83 @@
 }
 
 // SymOff returns the offset of the i-th symbol.
-func (r *Reader) SymOff(i int) uint32 {
+func (r *Reader) SymOff(i uint32) uint32 {
 	return r.h.Offsets[BlkSymdef] + uint32(i*SymSize)
 }
 
 // Sym returns a pointer to the i-th symbol.
-func (r *Reader) Sym(i int) *Sym {
+func (r *Reader) Sym(i uint32) *Sym {
 	off := r.SymOff(i)
 	return (*Sym)(unsafe.Pointer(&r.b[off]))
 }
 
 // NReloc returns the number of relocations of the i-th symbol.
-func (r *Reader) NReloc(i int) int {
+func (r *Reader) NReloc(i uint32) int {
 	relocIdxOff := r.h.Offsets[BlkRelocIdx] + uint32(i*4)
 	return int(r.uint32At(relocIdxOff+4) - r.uint32At(relocIdxOff))
 }
 
 // RelocOff returns the offset of the j-th relocation of the i-th symbol.
-func (r *Reader) RelocOff(i int, j int) uint32 {
+func (r *Reader) RelocOff(i uint32, j int) uint32 {
 	relocIdxOff := r.h.Offsets[BlkRelocIdx] + uint32(i*4)
 	relocIdx := r.uint32At(relocIdxOff)
 	return r.h.Offsets[BlkReloc] + (relocIdx+uint32(j))*uint32(RelocSize)
 }
 
 // Reloc returns a pointer to the j-th relocation of the i-th symbol.
-func (r *Reader) Reloc(i int, j int) *Reloc {
+func (r *Reader) Reloc(i uint32, j int) *Reloc {
 	off := r.RelocOff(i, j)
 	return (*Reloc)(unsafe.Pointer(&r.b[off]))
 }
 
 // Relocs returns a pointer to the relocations of the i-th symbol.
-func (r *Reader) Relocs(i int) []Reloc {
+func (r *Reader) Relocs(i uint32) []Reloc {
 	off := r.RelocOff(i, 0)
 	n := r.NReloc(i)
 	return (*[1 << 20]Reloc)(unsafe.Pointer(&r.b[off]))[:n:n]
 }
 
 // NAux returns the number of aux symbols of the i-th symbol.
-func (r *Reader) NAux(i int) int {
-	auxIdxOff := r.h.Offsets[BlkAuxIdx] + uint32(i*4)
+func (r *Reader) NAux(i uint32) int {
+	auxIdxOff := r.h.Offsets[BlkAuxIdx] + i*4
 	return int(r.uint32At(auxIdxOff+4) - r.uint32At(auxIdxOff))
 }
 
 // AuxOff returns the offset of the j-th aux symbol of the i-th symbol.
-func (r *Reader) AuxOff(i int, j int) uint32 {
-	auxIdxOff := r.h.Offsets[BlkAuxIdx] + uint32(i*4)
+func (r *Reader) AuxOff(i uint32, j int) uint32 {
+	auxIdxOff := r.h.Offsets[BlkAuxIdx] + i*4
 	auxIdx := r.uint32At(auxIdxOff)
 	return r.h.Offsets[BlkAux] + (auxIdx+uint32(j))*uint32(AuxSize)
 }
 
 // Aux returns a pointer to the j-th aux symbol of the i-th symbol.
-func (r *Reader) Aux(i int, j int) *Aux {
+func (r *Reader) Aux(i uint32, j int) *Aux {
 	off := r.AuxOff(i, j)
 	return (*Aux)(unsafe.Pointer(&r.b[off]))
 }
 
 // Auxs returns the aux symbols of the i-th symbol.
-func (r *Reader) Auxs(i int) []Aux {
+func (r *Reader) Auxs(i uint32) []Aux {
 	off := r.AuxOff(i, 0)
 	n := r.NAux(i)
 	return (*[1 << 20]Aux)(unsafe.Pointer(&r.b[off]))[:n:n]
 }
 
 // DataOff returns the offset of the i-th symbol's data.
-func (r *Reader) DataOff(i int) uint32 {
-	dataIdxOff := r.h.Offsets[BlkDataIdx] + uint32(i*4)
+func (r *Reader) DataOff(i uint32) uint32 {
+	dataIdxOff := r.h.Offsets[BlkDataIdx] + i*4
 	return r.h.Offsets[BlkData] + r.uint32At(dataIdxOff)
 }
 
 // DataSize returns the size of the i-th symbol's data.
-func (r *Reader) DataSize(i int) int {
-	dataIdxOff := r.h.Offsets[BlkDataIdx] + uint32(i*4)
+func (r *Reader) DataSize(i uint32) int {
+	dataIdxOff := r.h.Offsets[BlkDataIdx] + i*4
 	return int(r.uint32At(dataIdxOff+4) - r.uint32At(dataIdxOff))
 }
 
 // Data returns the i-th symbol's data.
-func (r *Reader) Data(i int) []byte {
-	dataIdxOff := r.h.Offsets[BlkDataIdx] + uint32(i*4)
+func (r *Reader) Data(i uint32) []byte {
+	dataIdxOff := r.h.Offsets[BlkDataIdx] + i*4
 	base := r.h.Offsets[BlkData]
 	off := r.uint32At(dataIdxOff)
 	end := r.uint32At(dataIdxOff + 4)
@@ -728,3 +729,6 @@
 func (r *Reader) Flags() uint32 {
 	return r.h.Flags
 }
+
+func (r *Reader) Shared() bool            { return r.Flags()&ObjFlagShared != 0 }
+func (r *Reader) NeedNameExpansion() bool { return r.Flags()&ObjFlagNeedNameExpansion != 0 }
diff --git a/src/cmd/internal/obj/link.go b/src/cmd/internal/obj/link.go
index f860b93..d9628bf 100644
--- a/src/cmd/internal/obj/link.go
+++ b/src/cmd/internal/obj/link.go
@@ -656,7 +656,6 @@
 	Flag_linkshared    bool
 	Flag_optimize      bool
 	Flag_locationlists bool
-	Flag_go115newobj   bool // use new object file format
 	Retpoline          bool // emit use of retpoline stubs for indirect jmp/call
 	Bso                *bufio.Writer
 	Pathname           string
diff --git a/src/cmd/internal/obj/objfile.go b/src/cmd/internal/obj/objfile.go
index 93c3138..c0194c5 100644
--- a/src/cmd/internal/obj/objfile.go
+++ b/src/cmd/internal/obj/objfile.go
@@ -2,234 +2,18 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// Writing of Go object files.
-
 package obj
 
 import (
-	"bufio"
-	"cmd/internal/bio"
 	"cmd/internal/dwarf"
 	"cmd/internal/objabi"
 	"cmd/internal/sys"
 	"fmt"
 	"io"
-	"log"
-	"path/filepath"
 	"sort"
-	"strings"
 	"sync"
 )
 
-// objWriter writes Go object files.
-type objWriter struct {
-	wr   *bufio.Writer
-	ctxt *Link
-	// Temporary buffer for zigzag int writing.
-	varintbuf [10]uint8
-
-	// Number of objects written of each type.
-	nRefs     int
-	nData     int
-	nReloc    int
-	nPcdata   int
-	nFuncdata int
-	nFile     int
-
-	pkgpath string // the package import path (escaped), "" if unknown
-}
-
-func (w *objWriter) addLengths(s *LSym) {
-	w.nData += len(s.P)
-	w.nReloc += len(s.R)
-
-	if s.Type != objabi.STEXT {
-		return
-	}
-
-	pc := &s.Func.Pcln
-
-	data := 0
-	data += len(pc.Pcsp.P)
-	data += len(pc.Pcfile.P)
-	data += len(pc.Pcline.P)
-	data += len(pc.Pcinline.P)
-	for _, pcd := range pc.Pcdata {
-		data += len(pcd.P)
-	}
-
-	w.nData += data
-	w.nPcdata += len(pc.Pcdata)
-
-	w.nFuncdata += len(pc.Funcdataoff)
-	w.nFile += len(pc.File)
-}
-
-func (w *objWriter) writeLengths() {
-	w.writeInt(int64(w.nData))
-	w.writeInt(int64(w.nReloc))
-	w.writeInt(int64(w.nPcdata))
-	w.writeInt(int64(0)) // TODO: remove at next object file rev
-	w.writeInt(int64(w.nFuncdata))
-	w.writeInt(int64(w.nFile))
-}
-
-func newObjWriter(ctxt *Link, b *bufio.Writer, pkgpath string) *objWriter {
-	return &objWriter{
-		ctxt:    ctxt,
-		wr:      b,
-		pkgpath: objabi.PathToPrefix(pkgpath),
-	}
-}
-
-func WriteObjFile(ctxt *Link, bout *bio.Writer, pkgpath string) {
-	if ctxt.Flag_go115newobj {
-		WriteObjFile2(ctxt, bout, pkgpath)
-		return
-	}
-
-	b := bout.Writer
-	w := newObjWriter(ctxt, b, pkgpath)
-
-	// Magic header
-	w.wr.WriteString("\x00go114ld")
-
-	// Version
-	w.wr.WriteByte(1)
-
-	// Autolib
-	for _, p := range ctxt.Imports {
-		w.writeString(p.Pkg)
-		// This object format ignores p.Fingerprint.
-	}
-	w.writeString("")
-
-	// DWARF File Table
-	fileTable := ctxt.PosTable.DebugLinesFileTable()
-	w.writeInt(int64(len(fileTable)))
-	for _, str := range fileTable {
-		w.writeString(filepath.ToSlash(str))
-	}
-
-	// Symbol references
-	for _, s := range ctxt.Text {
-		w.writeRefs(s)
-		w.addLengths(s)
-	}
-
-	if ctxt.Headtype == objabi.Haix {
-		// Data must be sorted to keep a constant order in TOC symbols.
-		// As they are created during Progedit, two symbols can be switched between
-		// two different compilations. Therefore, BuildID will be different.
-		// TODO: find a better place and optimize to only sort TOC symbols
-		sort.Slice(ctxt.Data, func(i, j int) bool {
-			return ctxt.Data[i].Name < ctxt.Data[j].Name
-		})
-	}
-
-	for _, s := range ctxt.Data {
-		w.writeRefs(s)
-		w.addLengths(s)
-	}
-	for _, s := range ctxt.ABIAliases {
-		w.writeRefs(s)
-		w.addLengths(s)
-	}
-	// End symbol references
-	w.wr.WriteByte(0xff)
-
-	// Lengths
-	w.writeLengths()
-
-	// Data block
-	for _, s := range ctxt.Text {
-		w.wr.Write(s.P)
-		pc := &s.Func.Pcln
-		w.wr.Write(pc.Pcsp.P)
-		w.wr.Write(pc.Pcfile.P)
-		w.wr.Write(pc.Pcline.P)
-		w.wr.Write(pc.Pcinline.P)
-		for _, pcd := range pc.Pcdata {
-			w.wr.Write(pcd.P)
-		}
-	}
-	for _, s := range ctxt.Data {
-		if len(s.P) > 0 {
-			switch s.Type {
-			case objabi.SBSS, objabi.SNOPTRBSS, objabi.STLSBSS:
-				ctxt.Diag("cannot provide data for %v sym %v", s.Type, s.Name)
-			}
-		}
-		w.wr.Write(s.P)
-	}
-
-	// Symbols
-	for _, s := range ctxt.Text {
-		w.writeSym(s)
-	}
-	for _, s := range ctxt.Data {
-		w.writeSym(s)
-	}
-	for _, s := range ctxt.ABIAliases {
-		w.writeSym(s)
-	}
-
-	// Magic footer
-	w.wr.WriteString("\xffgo114ld")
-}
-
-// Symbols are prefixed so their content doesn't get confused with the magic footer.
-const symPrefix = 0xfe
-
-func (w *objWriter) writeRef(s *LSym, isPath bool) {
-	if s == nil || s.RefIdx != 0 {
-		return
-	}
-	w.wr.WriteByte(symPrefix)
-	if isPath {
-		w.writeString(filepath.ToSlash(s.Name))
-	} else if w.pkgpath != "" {
-		// w.pkgpath is already escaped.
-		n := strings.Replace(s.Name, "\"\".", w.pkgpath+".", -1)
-		w.writeString(n)
-	} else {
-		w.writeString(s.Name)
-	}
-	// Write ABI/static information.
-	abi := int64(s.ABI())
-	if s.Static() {
-		abi = -1
-	}
-	w.writeInt(abi)
-	w.nRefs++
-	s.RefIdx = w.nRefs
-}
-
-func (w *objWriter) writeRefs(s *LSym) {
-	w.writeRef(s, false)
-	w.writeRef(s.Gotype, false)
-	for _, r := range s.R {
-		w.writeRef(r.Sym, false)
-	}
-
-	if s.Type == objabi.STEXT {
-		pc := &s.Func.Pcln
-		for _, d := range pc.Funcdata {
-			w.writeRef(d, false)
-		}
-		for _, f := range pc.File {
-			fsym := w.ctxt.Lookup(f)
-			w.writeRef(fsym, true)
-		}
-		for _, call := range pc.InlTree.nodes {
-			w.writeRef(call.Func, false)
-			f, _ := linkgetlineFromPos(w.ctxt, call.Pos)
-			fsym := w.ctxt.Lookup(f)
-			w.writeRef(fsym, true)
-		}
-	}
-}
-
 func (ctxt *Link) writeSymDebug(s *LSym) {
 	ctxt.writeSymDebugNamed(s, s.Name)
 }
@@ -311,138 +95,6 @@
 	}
 }
 
-func (w *objWriter) writeSym(s *LSym) {
-	ctxt := w.ctxt
-	if ctxt.Debugasm > 0 {
-		w.ctxt.writeSymDebug(s)
-	}
-
-	w.wr.WriteByte(symPrefix)
-	w.wr.WriteByte(byte(s.Type))
-	w.writeRefIndex(s)
-	flags := int64(0)
-	if s.DuplicateOK() {
-		flags |= 1
-	}
-	if s.Local() {
-		flags |= 1 << 1
-	}
-	if s.MakeTypelink() {
-		flags |= 1 << 2
-	}
-	w.writeInt(flags)
-	w.writeInt(s.Size)
-	w.writeRefIndex(s.Gotype)
-	w.writeInt(int64(len(s.P)))
-
-	w.writeInt(int64(len(s.R)))
-	var r *Reloc
-	for i := range s.R {
-		r = &s.R[i]
-		w.writeInt(int64(r.Off))
-		w.writeInt(int64(r.Siz))
-		w.writeInt(int64(r.Type))
-		w.writeInt(r.Add)
-		w.writeRefIndex(r.Sym)
-	}
-
-	if s.Type != objabi.STEXT {
-		return
-	}
-
-	w.writeInt(int64(s.Func.Args))
-	w.writeInt(int64(s.Func.Locals))
-	w.writeInt(int64(s.Func.Align))
-	w.writeBool(s.NoSplit())
-	flags = int64(0)
-	if s.Leaf() {
-		flags |= 1
-	}
-	if s.CFunc() {
-		flags |= 1 << 1
-	}
-	if s.ReflectMethod() {
-		flags |= 1 << 2
-	}
-	if ctxt.Flag_shared {
-		flags |= 1 << 3
-	}
-	if s.TopFrame() {
-		flags |= 1 << 4
-	}
-	w.writeInt(flags)
-	w.writeInt(int64(0)) // TODO: remove at next object file rev
-
-	pc := &s.Func.Pcln
-	w.writeInt(int64(len(pc.Pcsp.P)))
-	w.writeInt(int64(len(pc.Pcfile.P)))
-	w.writeInt(int64(len(pc.Pcline.P)))
-	w.writeInt(int64(len(pc.Pcinline.P)))
-	w.writeInt(int64(len(pc.Pcdata)))
-	for _, pcd := range pc.Pcdata {
-		w.writeInt(int64(len(pcd.P)))
-	}
-	w.writeInt(int64(len(pc.Funcdataoff)))
-	for i := range pc.Funcdataoff {
-		w.writeRefIndex(pc.Funcdata[i])
-	}
-	for i := range pc.Funcdataoff {
-		w.writeInt(pc.Funcdataoff[i])
-	}
-	w.writeInt(int64(len(pc.File)))
-	for _, f := range pc.File {
-		fsym := ctxt.Lookup(f)
-		w.writeRefIndex(fsym)
-	}
-	w.writeInt(int64(len(pc.InlTree.nodes)))
-	for _, call := range pc.InlTree.nodes {
-		w.writeInt(int64(call.Parent))
-		f, l := linkgetlineFromPos(w.ctxt, call.Pos)
-		fsym := ctxt.Lookup(f)
-		w.writeRefIndex(fsym)
-		w.writeInt(int64(l))
-		w.writeRefIndex(call.Func)
-		w.writeInt(int64(call.ParentPC))
-	}
-}
-
-func (w *objWriter) writeBool(b bool) {
-	if b {
-		w.writeInt(1)
-	} else {
-		w.writeInt(0)
-	}
-}
-
-func (w *objWriter) writeInt(sval int64) {
-	var v uint64
-	uv := (uint64(sval) << 1) ^ uint64(sval>>63)
-	p := w.varintbuf[:]
-	for v = uv; v >= 0x80; v >>= 7 {
-		p[0] = uint8(v | 0x80)
-		p = p[1:]
-	}
-	p[0] = uint8(v)
-	p = p[1:]
-	w.wr.Write(w.varintbuf[:len(w.varintbuf)-len(p)])
-}
-
-func (w *objWriter) writeString(s string) {
-	w.writeInt(int64(len(s)))
-	w.wr.WriteString(s)
-}
-
-func (w *objWriter) writeRefIndex(s *LSym) {
-	if s == nil {
-		w.writeInt(0)
-		return
-	}
-	if s.RefIdx == 0 {
-		log.Fatalln("writing an unreferenced symbol", s.Name)
-	}
-	w.writeInt(int64(s.RefIdx))
-}
-
 // relocByOff sorts relocations by their offsets.
 type relocByOff []Reloc
 
@@ -510,17 +162,11 @@
 func (c dwCtxt) AddFileRef(s dwarf.Sym, f interface{}) {
 	ls := s.(*LSym)
 	rsym := f.(*LSym)
-	if c.Link.Flag_go115newobj {
-		fidx := c.Link.PosTable.FileIndex(rsym.Name)
-		// Note the +1 here -- the value we're writing is going to be an
-		// index into the DWARF line table file section, whose entries
-		// are numbered starting at 1, not 0.
-		ls.WriteInt(c.Link, ls.Size, 4, int64(fidx+1))
-	} else {
-		ls.WriteAddr(c.Link, ls.Size, 4, rsym, 0)
-		r := &ls.R[len(ls.R)-1]
-		r.Type = objabi.R_DWARFFILEREF
-	}
+	fidx := c.Link.PosTable.FileIndex(rsym.Name)
+	// Note the +1 here -- the value we're writing is going to be an
+	// index into the DWARF line table file section, whose entries
+	// are numbered starting at 1, not 0.
+	ls.WriteInt(c.Link, ls.Size, 4, int64(fidx+1))
 }
 
 func (c dwCtxt) CurrentOffset(s dwarf.Sym) int64 {
@@ -558,28 +204,19 @@
 		ctxt.Diag("dwarfSym of non-TEXT %v", s)
 	}
 	if s.Func.dwarfInfoSym == nil {
-		if ctxt.Flag_go115newobj {
-			s.Func.dwarfInfoSym = &LSym{
-				Type: objabi.SDWARFINFO,
+		s.Func.dwarfInfoSym = &LSym{
+			Type: objabi.SDWARFFCN,
+		}
+		if ctxt.Flag_locationlists {
+			s.Func.dwarfLocSym = &LSym{
+				Type: objabi.SDWARFLOC,
 			}
-			if ctxt.Flag_locationlists {
-				s.Func.dwarfLocSym = &LSym{
-					Type: objabi.SDWARFLOC,
-				}
-			}
-			s.Func.dwarfRangesSym = &LSym{
-				Type: objabi.SDWARFRANGE,
-			}
-			s.Func.dwarfDebugLinesSym = &LSym{
-				Type: objabi.SDWARFLINES,
-			}
-		} else {
-			s.Func.dwarfInfoSym = ctxt.LookupDerived(s, dwarf.InfoPrefix+s.Name)
-			if ctxt.Flag_locationlists {
-				s.Func.dwarfLocSym = ctxt.LookupDerived(s, dwarf.LocPrefix+s.Name)
-			}
-			s.Func.dwarfRangesSym = ctxt.LookupDerived(s, dwarf.RangePrefix+s.Name)
-			s.Func.dwarfDebugLinesSym = ctxt.LookupDerived(s, dwarf.DebugLinesPrefix+s.Name)
+		}
+		s.Func.dwarfRangesSym = &LSym{
+			Type: objabi.SDWARFRANGE,
+		}
+		s.Func.dwarfDebugLinesSym = &LSym{
+			Type: objabi.SDWARFLINES,
 		}
 		if s.WasInlined() {
 			s.Func.dwarfAbsFnSym = ctxt.DwFixups.AbsFuncDwarfSym(s)
@@ -659,7 +296,7 @@
 		return
 	}
 	s := ctxt.LookupInit(dwarf.ConstInfoPrefix+myimportpath, func(s *LSym) {
-		s.Type = objabi.SDWARFINFO
+		s.Type = objabi.SDWARFCONST
 		ctxt.Data = append(ctxt.Data, s)
 	})
 	dwarf.PutIntConst(dwCtxt{ctxt}, s, ctxt.Lookup(dwarf.InfoPrefix+typename), myimportpath+"."+name, val)
@@ -785,7 +422,7 @@
 	// the back end.
 	absfn := ft.ctxt.LookupDerived(s, dwarf.InfoPrefix+s.Name+dwarf.AbstractFuncSuffix)
 	absfn.Set(AttrDuplicateOK, true)
-	absfn.Type = objabi.SDWARFINFO
+	absfn.Type = objabi.SDWARFABSFCN
 	ft.ctxt.Data = append(ft.ctxt.Data, absfn)
 
 	// In the case of "late" inlining (inlines that happen during
diff --git a/src/cmd/internal/obj/objfile2.go b/src/cmd/internal/obj/objfile2.go
index 05400a1..591df09 100644
--- a/src/cmd/internal/obj/objfile2.go
+++ b/src/cmd/internal/obj/objfile2.go
@@ -17,7 +17,7 @@
 )
 
 // Entry point of writing new object file.
-func WriteObjFile2(ctxt *Link, b *bio.Writer, pkgpath string) {
+func WriteObjFile(ctxt *Link, b *bio.Writer, pkgpath string) {
 
 	debugAsmEmit(ctxt)
 
@@ -38,6 +38,9 @@
 	if ctxt.Flag_shared {
 		flags |= goobj2.ObjFlagShared
 	}
+	if pkgpath == "" {
+		flags |= goobj2.ObjFlagNeedNameExpansion
+	}
 	h := goobj2.Header{
 		Magic:       goobj2.Magic,
 		Fingerprint: ctxt.Fingerprint,
@@ -464,7 +467,8 @@
 	// Most aux symbols (ex: funcdata) are not interesting--
 	// pick out just the DWARF ones for now.
 	if aux.Type != objabi.SDWARFLOC &&
-		aux.Type != objabi.SDWARFINFO &&
+		aux.Type != objabi.SDWARFFCN &&
+		aux.Type != objabi.SDWARFABSFCN &&
 		aux.Type != objabi.SDWARFLINES &&
 		aux.Type != objabi.SDWARFRANGE {
 		return
diff --git a/src/cmd/internal/obj/plist.go b/src/cmd/internal/obj/plist.go
index 73b6e8b..d4f9089 100644
--- a/src/cmd/internal/obj/plist.go
+++ b/src/cmd/internal/obj/plist.go
@@ -139,26 +139,7 @@
 	ctxt.Text = append(ctxt.Text, s)
 
 	// Set up DWARF entries for s
-	info, loc, ranges, _, lines := ctxt.dwarfSym(s)
-
-	// When using new object files, the DWARF symbols are unnamed aux
-	// symbols and don't need to be added to ctxt.Data.
-	// But the old object file still needs them.
-	if !ctxt.Flag_go115newobj {
-		info.Type = objabi.SDWARFINFO
-		info.Set(AttrDuplicateOK, s.DuplicateOK())
-		if loc != nil {
-			loc.Type = objabi.SDWARFLOC
-			loc.Set(AttrDuplicateOK, s.DuplicateOK())
-			ctxt.Data = append(ctxt.Data, loc)
-		}
-		ranges.Type = objabi.SDWARFRANGE
-		ranges.Set(AttrDuplicateOK, s.DuplicateOK())
-		ctxt.Data = append(ctxt.Data, info, ranges)
-		lines.Type = objabi.SDWARFLINES
-		lines.Set(AttrDuplicateOK, s.DuplicateOK())
-		ctxt.Data = append(ctxt.Data, lines)
-	}
+	ctxt.dwarfSym(s)
 }
 
 func (ctxt *Link) Globl(s *LSym, size int64, flag int) {
diff --git a/src/cmd/internal/obj/sym.go b/src/cmd/internal/obj/sym.go
index 400a741..bfc405c 100644
--- a/src/cmd/internal/obj/sym.go
+++ b/src/cmd/internal/obj/sym.go
@@ -34,7 +34,6 @@
 import (
 	"cmd/internal/goobj2"
 	"cmd/internal/objabi"
-	"crypto/md5"
 	"fmt"
 	"log"
 	"math"
@@ -164,11 +163,7 @@
 // Assign index to symbols.
 // asm is set to true if this is called by the assembler (i.e. not the compiler),
 // in which case all the symbols are non-package (for now).
-func (ctxt *Link) NumberSyms(asm bool) {
-	if !ctxt.Flag_go115newobj {
-		return
-	}
-
+func (ctxt *Link) NumberSyms() {
 	if ctxt.Headtype == objabi.Haix {
 		// Data must be sorted to keep a constant order in TOC symbols.
 		// As they are created during Progedit, two symbols can be switched between
@@ -185,7 +180,7 @@
 
 	var idx, nonpkgidx int32 = 0, 0
 	ctxt.traverseSyms(traverseDefs, func(s *LSym) {
-		if isNonPkgSym(ctxt, asm, s) {
+		if isNonPkgSym(ctxt, s) {
 			s.PkgIdx = goobj2.PkgIdxNone
 			s.SymIdx = nonpkgidx
 			if nonpkgidx != int32(len(ctxt.nonpkgdefs)) {
@@ -242,21 +237,12 @@
 		ctxt.pkgIdx[pkg] = ipkg
 		ipkg++
 	})
-
-	// Compute a fingerprint of the indices, for exporting.
-	if !asm {
-		h := md5.New()
-		for _, s := range ctxt.defs {
-			h.Write([]byte(s.Name))
-		}
-		copy(ctxt.Fingerprint[:], h.Sum(nil)[:])
-	}
 }
 
 // Returns whether s is a non-package symbol, which needs to be referenced
 // by name instead of by index.
-func isNonPkgSym(ctxt *Link, asm bool, s *LSym) bool {
-	if asm && !s.Static() {
+func isNonPkgSym(ctxt *Link, s *LSym) bool {
+	if ctxt.IsAsm && !s.Static() {
 		// asm symbols are referenced by name only, except static symbols
 		// which are file-local and can be referenced by index.
 		return true
diff --git a/src/cmd/internal/objabi/symkind.go b/src/cmd/internal/objabi/symkind.go
index 374aaa6..6c99112 100644
--- a/src/cmd/internal/objabi/symkind.go
+++ b/src/cmd/internal/objabi/symkind.go
@@ -56,7 +56,12 @@
 	// Thread-local data that is initially all 0s
 	STLSBSS
 	// Debugging data
-	SDWARFINFO
+	SDWARFCUINFO
+	SDWARFCONST
+	SDWARFFCN
+	SDWARFABSFCN
+	SDWARFTYPE
+	SDWARFVAR
 	SDWARFRANGE
 	SDWARFLOC
 	SDWARFLINES
diff --git a/src/cmd/internal/objabi/symkind_string.go b/src/cmd/internal/objabi/symkind_string.go
index 919a666..1b1c394 100644
--- a/src/cmd/internal/objabi/symkind_string.go
+++ b/src/cmd/internal/objabi/symkind_string.go
@@ -16,17 +16,22 @@
 	_ = x[SBSS-5]
 	_ = x[SNOPTRBSS-6]
 	_ = x[STLSBSS-7]
-	_ = x[SDWARFINFO-8]
-	_ = x[SDWARFRANGE-9]
-	_ = x[SDWARFLOC-10]
-	_ = x[SDWARFLINES-11]
-	_ = x[SABIALIAS-12]
-	_ = x[SLIBFUZZER_EXTRA_COUNTER-13]
+	_ = x[SDWARFCUINFO-8]
+	_ = x[SDWARFCONST-9]
+	_ = x[SDWARFFCN-10]
+	_ = x[SDWARFABSFCN-11]
+	_ = x[SDWARFTYPE-12]
+	_ = x[SDWARFVAR-13]
+	_ = x[SDWARFRANGE-14]
+	_ = x[SDWARFLOC-15]
+	_ = x[SDWARFLINES-16]
+	_ = x[SABIALIAS-17]
+	_ = x[SLIBFUZZER_EXTRA_COUNTER-18]
 }
 
-const _SymKind_name = "SxxxSTEXTSRODATASNOPTRDATASDATASBSSSNOPTRBSSSTLSBSSSDWARFINFOSDWARFRANGESDWARFLOCSDWARFLINESSABIALIASSLIBFUZZER_EXTRA_COUNTER"
+const _SymKind_name = "SxxxSTEXTSRODATASNOPTRDATASDATASBSSSNOPTRBSSSTLSBSSSDWARFCUINFOSDWARFCONSTSDWARFFCNSDWARFABSFCNSDWARFTYPESDWARFVARSDWARFRANGESDWARFLOCSDWARFLINESSABIALIASSLIBFUZZER_EXTRA_COUNTER"
 
-var _SymKind_index = [...]uint8{0, 4, 9, 16, 26, 31, 35, 44, 51, 61, 72, 81, 92, 101, 125}
+var _SymKind_index = [...]uint8{0, 4, 9, 16, 26, 31, 35, 44, 51, 63, 74, 83, 95, 105, 114, 125, 134, 145, 154, 178}
 
 func (i SymKind) String() string {
 	if i >= SymKind(len(_SymKind_index)-1) {
diff --git a/src/cmd/link/dwarf_test.go b/src/cmd/link/dwarf_test.go
index a9f58db..ac6937c 100644
--- a/src/cmd/link/dwarf_test.go
+++ b/src/cmd/link/dwarf_test.go
@@ -191,6 +191,13 @@
 	if err := exec.Command("xcrun", "--help").Run(); err != nil {
 		t.Skipf("error running xcrun, required for iOS cross build: %v", err)
 	}
+	// Check to see if the ios tools are installed. It's possible to have the command line tools
+	// installed without the iOS sdk.
+	if output, err := exec.Command("xcodebuild -showsdks").CombinedOutput(); err != nil {
+		t.Skipf("error running xcodebuild, required for iOS cross build: %v", err)
+	} else if !strings.Contains(string(output), "iOS SDK") {
+		t.Skipf("iOS SDK not detected.")
+	}
 	cc := "CC=" + runtime.GOROOT() + "/misc/ios/clangwrap.sh"
 	// iOS doesn't allow unmapped segments, so iOS executables don't have DWARF.
 	testDWARF(t, "", false, cc, "CGO_ENABLED=1", "GOOS=darwin", "GOARCH=arm64")
diff --git a/src/cmd/link/internal/amd64/asm.go b/src/cmd/link/internal/amd64/asm.go
index b8dc0fc..659c03e 100644
--- a/src/cmd/link/internal/amd64/asm.go
+++ b/src/cmd/link/internal/amd64/asm.go
@@ -38,14 +38,13 @@
 	"cmd/link/internal/sym"
 	"debug/elf"
 	"log"
-	"sync"
 )
 
 func PADDR(x uint32) uint32 {
 	return x &^ 0x80000000
 }
 
-func gentext2(ctxt *ld.Link, ldr *loader.Loader) {
+func gentext(ctxt *ld.Link, ldr *loader.Loader) {
 	initfunc, addmoduledata := ld.PrepareAddmoduledata(ctxt)
 	if initfunc == nil {
 		return
@@ -61,7 +60,7 @@
 	//    0:	48 8d 3d 00 00 00 00 	lea    0x0(%rip),%rdi        # 7 <local.dso_init+0x7>
 	// 			3: R_X86_64_PC32	runtime.firstmoduledata-0x4
 	o(0x48, 0x8d, 0x3d)
-	initfunc.AddPCRelPlus(ctxt.Arch, ctxt.Moduledata2, 0)
+	initfunc.AddPCRelPlus(ctxt.Arch, ctxt.Moduledata, 0)
 	//    7:	e8 00 00 00 00       	callq  c <local.dso_init+0xc>
 	// 			8: R_X86_64_PLT32	runtime.addmoduledata-0x4
 	o(0xe8)
@@ -70,15 +69,7 @@
 	o(0xc3)
 }
 
-// makeWritable makes a readonly symbol writable if we do opcode rewriting.
-func makeWritable(s *sym.Symbol) {
-	if s.Attr.ReadOnly() {
-		s.Attr.Set(sym.AttrReadOnly, false)
-		s.P = append([]byte(nil), s.P...)
-	}
-}
-
-func adddynrel2(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym, r loader.Reloc2, rIdx int) bool {
+func adddynrel(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym, r loader.Reloc2, rIdx int) bool {
 	targ := r.Sym()
 	var targType sym.SymKind
 	if targ != 0 {
@@ -124,8 +115,8 @@
 		su.SetRelocType(rIdx, objabi.R_PCREL)
 		su.SetRelocAdd(rIdx, r.Add()+4)
 		if targType == sym.SDYNIMPORT {
-			addpltsym2(target, ldr, syms, targ)
-			su.SetRelocSym(rIdx, syms.PLT2)
+			addpltsym(target, ldr, syms, targ)
+			su.SetRelocSym(rIdx, syms.PLT)
 			su.SetRelocAdd(rIdx, r.Add()+int64(ldr.SymPlt(targ)))
 		}
 
@@ -151,10 +142,10 @@
 
 		// fall back to using GOT and hope for the best (CMOV*)
 		// TODO: just needs relocation, no need to put in .dynsym
-		addgotsym2(target, ldr, syms, targ)
+		ld.AddGotSym(target, ldr, syms, targ, uint32(elf.R_X86_64_GLOB_DAT))
 
 		su.SetRelocType(rIdx, objabi.R_PCREL)
-		su.SetRelocSym(rIdx, syms.GOT2)
+		su.SetRelocSym(rIdx, syms.GOT)
 		su.SetRelocAdd(rIdx, r.Add()+4+int64(ldr.SymGot(targ)))
 		return true
 
@@ -187,9 +178,9 @@
 
 	case objabi.MachoRelocOffset + ld.MACHO_X86_64_RELOC_BRANCH*2 + 1:
 		if targType == sym.SDYNIMPORT {
-			addpltsym2(target, ldr, syms, targ)
+			addpltsym(target, ldr, syms, targ)
 			su := ldr.MakeSymbolUpdater(s)
-			su.SetRelocSym(rIdx, syms.PLT2)
+			su.SetRelocSym(rIdx, syms.PLT)
 			su.SetRelocType(rIdx, objabi.R_PCREL)
 			su.SetRelocAdd(rIdx, int64(ldr.SymPlt(targ)))
 			return true
@@ -232,10 +223,10 @@
 		if targType != sym.SDYNIMPORT {
 			ldr.Errorf(s, "unexpected GOT reloc for non-dynamic symbol %s", ldr.SymName(targ))
 		}
-		addgotsym2(target, ldr, syms, targ)
+		ld.AddGotSym(target, ldr, syms, targ, uint32(elf.R_X86_64_GLOB_DAT))
 		su := ldr.MakeSymbolUpdater(s)
 		su.SetRelocType(rIdx, objabi.R_PCREL)
-		su.SetRelocSym(rIdx, syms.GOT2)
+		su.SetRelocSym(rIdx, syms.GOT)
 		su.SetRelocAdd(rIdx, r.Add()+int64(ldr.SymGot(targ)))
 		return true
 	}
@@ -257,9 +248,9 @@
 		}
 		// Internal linking, for both ELF and Mach-O.
 		// Build a PLT entry and change the relocation target to that entry.
-		addpltsym2(target, ldr, syms, targ)
+		addpltsym(target, ldr, syms, targ)
 		su := ldr.MakeSymbolUpdater(s)
-		su.SetRelocSym(rIdx, syms.PLT2)
+		su.SetRelocSym(rIdx, syms.PLT)
 		su.SetRelocAdd(rIdx, int64(ldr.SymPlt(targ)))
 		return true
 
@@ -267,17 +258,17 @@
 		if ldr.SymType(s) == sym.STEXT && target.IsElf() {
 			su := ldr.MakeSymbolUpdater(s)
 			if target.IsSolaris() {
-				addpltsym2(target, ldr, syms, targ)
-				su.SetRelocSym(rIdx, syms.PLT2)
+				addpltsym(target, ldr, syms, targ)
+				su.SetRelocSym(rIdx, syms.PLT)
 				su.SetRelocAdd(rIdx, r.Add()+int64(ldr.SymPlt(targ)))
 				return true
 			}
 			// The code is asking for the address of an external
 			// function. We provide it with the address of the
 			// correspondent GOT symbol.
-			addgotsym2(target, ldr, syms, targ)
+			ld.AddGotSym(target, ldr, syms, targ, uint32(elf.R_X86_64_GLOB_DAT))
 
-			su.SetRelocSym(rIdx, syms.GOT2)
+			su.SetRelocSym(rIdx, syms.GOT)
 			su.SetRelocAdd(rIdx, r.Add()+int64(ldr.SymGot(targ)))
 			return true
 		}
@@ -349,7 +340,7 @@
 			// AddAddrPlus is used for r_offset and r_addend to
 			// generate new R_ADDR relocations that will update
 			// these fields in the 'reloc' phase.
-			rela := ldr.MakeSymbolUpdater(syms.Rela2)
+			rela := ldr.MakeSymbolUpdater(syms.Rela)
 			rela.AddAddrPlus(target.Arch, s, int64(r.Off()))
 			if r.Siz() == 8 {
 				rela.AddUint64(target.Arch, ld.ELF64_R_INFO(0, uint32(elf.R_X86_64_RELATIVE)))
@@ -375,15 +366,15 @@
 			// just in case the C code assigns to the variable,
 			// and of course it only works for single pointers,
 			// but we only need to support cgo and that's all it needs.
-			ld.Adddynsym2(ldr, target, syms, targ)
+			ld.Adddynsym(ldr, target, syms, targ)
 
-			got := ldr.MakeSymbolUpdater(syms.GOT2)
+			got := ldr.MakeSymbolUpdater(syms.GOT)
 			su := ldr.MakeSymbolUpdater(s)
 			su.SetType(got.Type())
 			got.PrependSub(s)
 			su.SetValue(got.Size())
 			got.AddUint64(target.Arch, 0)
-			leg := ldr.MakeSymbolUpdater(syms.LinkEditGOT2)
+			leg := ldr.MakeSymbolUpdater(syms.LinkEditGOT)
 			leg.AddUint32(target.Arch, uint32(ldr.SymDynid(targ)))
 			su.SetRelocType(rIdx, objabi.ElfRelocOffset) // ignore during relocsym
 			return true
@@ -393,12 +384,12 @@
 	return false
 }
 
-func elfreloc2(ctxt *ld.Link, ldr *loader.Loader, s loader.Sym, r loader.ExtRelocView, sectoff int64) bool {
+func elfreloc1(ctxt *ld.Link, ldr *loader.Loader, s loader.Sym, r loader.ExtRelocView, sectoff int64) bool {
 	ctxt.Out.Write64(uint64(sectoff))
 
-	xsym := ldr.Syms[r.Xsym]
-	elfsym := ld.ElfSymForReloc(ctxt, xsym)
+	elfsym := ld.ElfSymForReloc(ctxt, r.Xsym)
 	siz := r.Siz()
+	xst := ldr.SymType(r.Xsym)
 	switch r.Type() {
 	default:
 		return false
@@ -424,7 +415,7 @@
 		}
 	case objabi.R_CALL:
 		if siz == 4 {
-			if xsym.Type == sym.SDYNIMPORT {
+			if xst == sym.SDYNIMPORT {
 				if ctxt.DynlinkingGo() {
 					ctxt.Out.Write64(uint64(elf.R_X86_64_PLT32) | uint64(elfsym)<<32)
 				} else {
@@ -438,7 +429,7 @@
 		}
 	case objabi.R_PCREL:
 		if siz == 4 {
-			if xsym.Type == sym.SDYNIMPORT && xsym.ElfType() == elf.STT_FUNC {
+			if xst == sym.SDYNIMPORT && ldr.SymElfType(r.Xsym) == elf.STT_FUNC {
 				ctxt.Out.Write64(uint64(elf.R_X86_64_PLT32) | uint64(elfsym)<<32)
 			} else {
 				ctxt.Out.Write64(uint64(elf.R_X86_64_PC32) | uint64(elfsym)<<32)
@@ -458,28 +449,29 @@
 	return true
 }
 
-func machoreloc1(arch *sys.Arch, out *ld.OutBuf, s *sym.Symbol, r *sym.Reloc, sectoff int64) bool {
+func machoreloc1(arch *sys.Arch, out *ld.OutBuf, ldr *loader.Loader, s loader.Sym, r loader.ExtRelocView, sectoff int64) bool {
 	var v uint32
 
 	rs := r.Xsym
+	rt := r.Type()
 
-	if rs.Type == sym.SHOSTOBJ || r.Type == objabi.R_PCREL || r.Type == objabi.R_GOTPCREL || r.Type == objabi.R_CALL {
-		if rs.Dynid < 0 {
-			ld.Errorf(s, "reloc %d (%s) to non-macho symbol %s type=%d (%s)", r.Type, sym.RelocName(arch, r.Type), rs.Name, rs.Type, rs.Type)
+	if ldr.SymType(rs) == sym.SHOSTOBJ || rt == objabi.R_PCREL || rt == objabi.R_GOTPCREL || rt == objabi.R_CALL {
+		if ldr.SymDynid(rs) < 0 {
+			ldr.Errorf(s, "reloc %d (%s) to non-macho symbol %s type=%d (%s)", rt, sym.RelocName(arch, rt), ldr.SymName(rs), ldr.SymType(rs), ldr.SymType(rs))
 			return false
 		}
 
-		v = uint32(rs.Dynid)
+		v = uint32(ldr.SymDynid(rs))
 		v |= 1 << 27 // external relocation
 	} else {
-		v = uint32(rs.Sect.Extnum)
+		v = uint32(ldr.SymSect(rs).Extnum)
 		if v == 0 {
-			ld.Errorf(s, "reloc %d (%s) to symbol %s in non-macho section %s type=%d (%s)", r.Type, sym.RelocName(arch, r.Type), rs.Name, rs.Sect.Name, rs.Type, rs.Type)
+			ldr.Errorf(s, "reloc %d (%s) to symbol %s in non-macho section %s type=%d (%s)", rt, sym.RelocName(arch, rt), ldr.SymName(rs), ldr.SymSect(rs).Name, ldr.SymType(rs), ldr.SymType(rs))
 			return false
 		}
 	}
 
-	switch r.Type {
+	switch rt {
 	default:
 		return false
 
@@ -499,7 +491,7 @@
 		v |= ld.MACHO_X86_64_RELOC_GOT_LOAD << 28
 	}
 
-	switch r.Siz {
+	switch r.Siz() {
 	default:
 		return false
 
@@ -521,20 +513,21 @@
 	return true
 }
 
-func pereloc1(arch *sys.Arch, out *ld.OutBuf, s *sym.Symbol, r *sym.Reloc, sectoff int64) bool {
+func pereloc1(arch *sys.Arch, out *ld.OutBuf, ldr *loader.Loader, s loader.Sym, r loader.ExtRelocView, sectoff int64) bool {
 	var v uint32
 
 	rs := r.Xsym
+	rt := r.Type()
 
-	if rs.Dynid < 0 {
-		ld.Errorf(s, "reloc %d (%s) to non-coff symbol %s type=%d (%s)", r.Type, sym.RelocName(arch, r.Type), rs.Name, rs.Type, rs.Type)
+	if ldr.SymDynid(rs) < 0 {
+		ldr.Errorf(s, "reloc %d (%s) to non-coff symbol %s type=%d (%s)", rt, sym.RelocName(arch, rt), ldr.SymName(rs), ldr.SymType(rs), ldr.SymType(rs))
 		return false
 	}
 
 	out.Write32(uint32(sectoff))
-	out.Write32(uint32(rs.Dynid))
+	out.Write32(uint32(ldr.SymDynid(rs)))
 
-	switch r.Type {
+	switch rt {
 	default:
 		return false
 
@@ -542,7 +535,7 @@
 		v = ld.IMAGE_REL_AMD64_SECREL
 
 	case objabi.R_ADDR:
-		if r.Siz == 8 {
+		if r.Siz() == 8 {
 			v = ld.IMAGE_REL_AMD64_ADDR64
 		} else {
 			v = ld.IMAGE_REL_AMD64_ADDR32
@@ -558,13 +551,13 @@
 	return true
 }
 
-func archreloc(target *ld.Target, syms *ld.ArchSyms, r *sym.Reloc, s *sym.Symbol, val int64) (int64, bool) {
-	return val, false
+func archreloc(*ld.Target, *loader.Loader, *ld.ArchSyms, loader.Reloc2, *loader.ExtReloc, loader.Sym, int64) (int64, bool, bool) {
+	return -1, false, false
 }
 
-func archrelocvariant(target *ld.Target, syms *ld.ArchSyms, r *sym.Reloc, s *sym.Symbol, t int64) int64 {
+func archrelocvariant(*ld.Target, *loader.Loader, loader.Reloc2, sym.RelocVariant, loader.Sym, int64) int64 {
 	log.Fatalf("unexpected relocation variant")
-	return t
+	return -1
 }
 
 func elfsetupplt(ctxt *ld.Link, plt, got *loader.SymbolBuilder, dynamic loader.Sym) {
@@ -592,17 +585,17 @@
 	}
 }
 
-func addpltsym2(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym) {
+func addpltsym(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym) {
 	if ldr.SymPlt(s) >= 0 {
 		return
 	}
 
-	ld.Adddynsym2(ldr, target, syms, s)
+	ld.Adddynsym(ldr, target, syms, s)
 
 	if target.IsElf() {
-		plt := ldr.MakeSymbolUpdater(syms.PLT2)
-		got := ldr.MakeSymbolUpdater(syms.GOTPLT2)
-		rela := ldr.MakeSymbolUpdater(syms.RelaPLT2)
+		plt := ldr.MakeSymbolUpdater(syms.PLT)
+		got := ldr.MakeSymbolUpdater(syms.GOTPLT)
+		rela := ldr.MakeSymbolUpdater(syms.RelaPLT)
 		if plt.Size() == 0 {
 			panic("plt is not set up")
 		}
@@ -645,11 +638,11 @@
 		// https://networkpx.blogspot.com/2009/09/about-lcdyldinfoonly-command.html
 		// has details about what we're avoiding.
 
-		addgotsym2(target, ldr, syms, s)
-		plt := ldr.MakeSymbolUpdater(syms.PLT2)
+		ld.AddGotSym(target, ldr, syms, s, uint32(elf.R_X86_64_GLOB_DAT))
+		plt := ldr.MakeSymbolUpdater(syms.PLT)
 
 		sDynid := ldr.SymDynid(s)
-		lep := ldr.MakeSymbolUpdater(syms.LinkEditPLT2)
+		lep := ldr.MakeSymbolUpdater(syms.LinkEditPLT)
 		lep.AddUint32(target.Arch, uint32(sDynid))
 
 		// jmpq *got+size(IP)
@@ -657,192 +650,11 @@
 
 		plt.AddUint8(0xff)
 		plt.AddUint8(0x25)
-		plt.AddPCRelPlus(target.Arch, syms.GOT2, int64(ldr.SymGot(s)))
+		plt.AddPCRelPlus(target.Arch, syms.GOT, int64(ldr.SymGot(s)))
 	} else {
 		ldr.Errorf(s, "addpltsym: unsupported binary format")
 	}
 }
-
-func addgotsym2(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym) {
-	if ldr.SymGot(s) >= 0 {
-		return
-	}
-
-	ld.Adddynsym2(ldr, target, syms, s)
-	got := ldr.MakeSymbolUpdater(syms.GOT2)
-	ldr.SetGot(s, int32(got.Size()))
-	got.AddUint64(target.Arch, 0)
-
-	if target.IsElf() {
-		rela := ldr.MakeSymbolUpdater(syms.Rela2)
-		rela.AddAddrPlus(target.Arch, got.Sym(), int64(ldr.SymGot(s)))
-		rela.AddUint64(target.Arch, ld.ELF64_R_INFO(uint32(ldr.SymDynid(s)), uint32(elf.R_X86_64_GLOB_DAT)))
-		rela.AddUint64(target.Arch, 0)
-	} else if target.IsDarwin() {
-		leg := ldr.MakeSymbolUpdater(syms.LinkEditGOT2)
-		leg.AddUint32(target.Arch, uint32(ldr.SymDynid(s)))
-	} else {
-		ldr.Errorf(s, "addgotsym: unsupported binary format")
-	}
-}
-
-func asmb(ctxt *ld.Link, _ *loader.Loader) {
-	if ctxt.IsELF {
-		ld.Asmbelfsetup()
-	}
-
-	var wg sync.WaitGroup
-	sect := ld.Segtext.Sections[0]
-	offset := sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff
-	f := func(ctxt *ld.Link, out *ld.OutBuf, start, length int64) {
-		// 0xCC is INT $3 - breakpoint instruction
-		ld.CodeblkPad(ctxt, out, start, length, []byte{0xCC})
-	}
-	ld.WriteParallel(&wg, f, ctxt, offset, sect.Vaddr, sect.Length)
-
-	for _, sect := range ld.Segtext.Sections[1:] {
-		offset := sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff
-		ld.WriteParallel(&wg, ld.Datblk, ctxt, offset, sect.Vaddr, sect.Length)
-	}
-
-	if ld.Segrodata.Filelen > 0 {
-		ld.WriteParallel(&wg, ld.Datblk, ctxt, ld.Segrodata.Fileoff, ld.Segrodata.Vaddr, ld.Segrodata.Filelen)
-	}
-
-	if ld.Segrelrodata.Filelen > 0 {
-		ld.WriteParallel(&wg, ld.Datblk, ctxt, ld.Segrelrodata.Fileoff, ld.Segrelrodata.Vaddr, ld.Segrelrodata.Filelen)
-	}
-
-	ld.WriteParallel(&wg, ld.Datblk, ctxt, ld.Segdata.Fileoff, ld.Segdata.Vaddr, ld.Segdata.Filelen)
-
-	ld.WriteParallel(&wg, ld.Dwarfblk, ctxt, ld.Segdwarf.Fileoff, ld.Segdwarf.Vaddr, ld.Segdwarf.Filelen)
-
-	wg.Wait()
-}
-
-func asmb2(ctxt *ld.Link) {
-	machlink := int64(0)
-	if ctxt.HeadType == objabi.Hdarwin {
-		machlink = ld.Domacholink(ctxt)
-	}
-
-	switch ctxt.HeadType {
-	default:
-		ld.Errorf(nil, "unknown header type %v", ctxt.HeadType)
-		fallthrough
-
-	case objabi.Hplan9:
-		break
-
-	case objabi.Hdarwin:
-		ld.Flag8 = true /* 64-bit addresses */
-
-	case objabi.Hlinux,
-		objabi.Hfreebsd,
-		objabi.Hnetbsd,
-		objabi.Hopenbsd,
-		objabi.Hdragonfly,
-		objabi.Hsolaris:
-		ld.Flag8 = true /* 64-bit addresses */
-
-	case objabi.Hwindows:
-		break
-	}
-
-	ld.Symsize = 0
-	ld.Spsize = 0
-	ld.Lcsize = 0
-	symo := int64(0)
-	if !*ld.FlagS {
-		switch ctxt.HeadType {
-		default:
-		case objabi.Hplan9:
-			*ld.FlagS = true
-			symo = int64(ld.Segdata.Fileoff + ld.Segdata.Filelen)
-
-		case objabi.Hdarwin:
-			symo = int64(ld.Segdwarf.Fileoff + uint64(ld.Rnd(int64(ld.Segdwarf.Filelen), int64(*ld.FlagRound))) + uint64(machlink))
-
-		case objabi.Hlinux,
-			objabi.Hfreebsd,
-			objabi.Hnetbsd,
-			objabi.Hopenbsd,
-			objabi.Hdragonfly,
-			objabi.Hsolaris:
-			symo = int64(ld.Segdwarf.Fileoff + ld.Segdwarf.Filelen)
-			symo = ld.Rnd(symo, int64(*ld.FlagRound))
-
-		case objabi.Hwindows:
-			symo = int64(ld.Segdwarf.Fileoff + ld.Segdwarf.Filelen)
-			symo = ld.Rnd(symo, ld.PEFILEALIGN)
-		}
-
-		ctxt.Out.SeekSet(symo)
-		switch ctxt.HeadType {
-		default:
-			if ctxt.IsELF {
-				ctxt.Out.SeekSet(symo)
-				ld.Asmelfsym(ctxt)
-				ctxt.Out.Write(ld.Elfstrdat)
-
-				if ctxt.LinkMode == ld.LinkExternal {
-					ld.Elfemitreloc(ctxt)
-				}
-			}
-
-		case objabi.Hplan9:
-			ld.Asmplan9sym(ctxt)
-
-			sym := ctxt.Syms.Lookup("pclntab", 0)
-			if sym != nil {
-				ld.Lcsize = int32(len(sym.P))
-				ctxt.Out.Write(sym.P)
-			}
-
-		case objabi.Hwindows:
-			// Do nothing
-
-		case objabi.Hdarwin:
-			if ctxt.LinkMode == ld.LinkExternal {
-				ld.Machoemitreloc(ctxt)
-			}
-		}
-	}
-
-	ctxt.Out.SeekSet(0)
-	switch ctxt.HeadType {
-	default:
-	case objabi.Hplan9: /* plan9 */
-		magic := int32(4*26*26 + 7)
-
-		magic |= 0x00008000                           /* fat header */
-		ctxt.Out.Write32b(uint32(magic))              /* magic */
-		ctxt.Out.Write32b(uint32(ld.Segtext.Filelen)) /* sizes */
-		ctxt.Out.Write32b(uint32(ld.Segdata.Filelen))
-		ctxt.Out.Write32b(uint32(ld.Segdata.Length - ld.Segdata.Filelen))
-		ctxt.Out.Write32b(uint32(ld.Symsize)) /* nsyms */
-		vl := ld.Entryvalue(ctxt)
-		ctxt.Out.Write32b(PADDR(uint32(vl))) /* va of entry */
-		ctxt.Out.Write32b(uint32(ld.Spsize)) /* sp offsets */
-		ctxt.Out.Write32b(uint32(ld.Lcsize)) /* line offsets */
-		ctxt.Out.Write64b(uint64(vl))        /* va of entry */
-
-	case objabi.Hdarwin:
-		ld.Asmbmacho(ctxt)
-
-	case objabi.Hlinux,
-		objabi.Hfreebsd,
-		objabi.Hnetbsd,
-		objabi.Hopenbsd,
-		objabi.Hdragonfly,
-		objabi.Hsolaris:
-		ld.Asmbelf(ctxt, symo)
-
-	case objabi.Hwindows:
-		ld.Asmbpe(ctxt)
-	}
-}
-
 func tlsIEtoLE(P []byte, off, size int) {
 	// Transform the PC-relative instruction into a constant load.
 	// That is,
diff --git a/src/cmd/link/internal/amd64/obj.go b/src/cmd/link/internal/amd64/obj.go
index 705827d..4c52574 100644
--- a/src/cmd/link/internal/amd64/obj.go
+++ b/src/cmd/link/internal/amd64/obj.go
@@ -50,16 +50,19 @@
 		Minalign:   minAlign,
 		Dwarfregsp: dwarfRegSP,
 		Dwarfreglr: dwarfRegLR,
+		// 0xCC is INT $3 - breakpoint instruction
+		CodePad: []byte{0xCC},
 
-		Adddynrel2:       adddynrel2,
+		Plan9Magic:  uint32(4*26*26 + 7),
+		Plan9_64Bit: true,
+
+		Adddynrel:        adddynrel,
 		Archinit:         archinit,
 		Archreloc:        archreloc,
 		Archrelocvariant: archrelocvariant,
-		Asmb:             asmb,
-		Asmb2:            asmb2,
-		Elfreloc2:        elfreloc2,
+		Elfreloc1:        elfreloc1,
 		Elfsetupplt:      elfsetupplt,
-		Gentext2:         gentext2,
+		Gentext:          gentext,
 		Machoreloc1:      machoreloc1,
 		PEreloc1:         pereloc1,
 		TLSIEtoLE:        tlsIEtoLE,
diff --git a/src/cmd/link/internal/arm/asm.go b/src/cmd/link/internal/arm/asm.go
index 903e621..1f78f76 100644
--- a/src/cmd/link/internal/arm/asm.go
+++ b/src/cmd/link/internal/arm/asm.go
@@ -39,7 +39,6 @@
 	"debug/elf"
 	"fmt"
 	"log"
-	"sync"
 )
 
 // This assembler:
@@ -63,7 +62,7 @@
 //    c:        00000004        .word   0x00000004
 //                      c: R_ARM_GOT_PREL       local.moduledata
 
-func gentext2(ctxt *ld.Link, ldr *loader.Loader) {
+func gentext(ctxt *ld.Link, ldr *loader.Loader) {
 	initfunc, addmoduledata := ld.PrepareAddmoduledata(ctxt)
 	if initfunc == nil {
 		return
@@ -91,7 +90,7 @@
 		Off:  12,
 		Size: 4,
 		Type: objabi.R_PCREL,
-		Sym:  ctxt.Moduledata2,
+		Sym:  ctxt.Moduledata,
 		Add:  4,
 	}
 	initfunc.AddReloc(rel2)
@@ -103,7 +102,7 @@
 	return int32((uint32(a))&0xff000000 | 0x00ffffff&uint32(a+b))
 }
 
-func adddynrel2(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym, r loader.Reloc2, rIdx int) bool {
+func adddynrel(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym, r loader.Reloc2, rIdx int) bool {
 
 	targ := r.Sym()
 	var targType sym.SymKind
@@ -124,8 +123,8 @@
 		su.SetRelocType(rIdx, objabi.R_CALLARM)
 
 		if targType == sym.SDYNIMPORT {
-			addpltsym2(target, ldr, syms, targ)
-			su.SetRelocSym(rIdx, syms.PLT2)
+			addpltsym(target, ldr, syms, targ)
+			su.SetRelocSym(rIdx, syms.PLT)
 			su.SetRelocAdd(rIdx, int64(braddoff(int32(r.Add()), ldr.SymPlt(targ)/4)))
 		}
 
@@ -137,9 +136,9 @@
 
 	case objabi.ElfRelocOffset + objabi.RelocType(elf.R_ARM_GOT32): // R_ARM_GOT_BREL
 		if targType != sym.SDYNIMPORT {
-			addgotsyminternal2(target, ldr, syms, targ)
+			addgotsyminternal(target, ldr, syms, targ)
 		} else {
-			addgotsym2(target, ldr, syms, targ)
+			ld.AddGotSym(target, ldr, syms, targ, uint32(elf.R_ARM_GLOB_DAT))
 		}
 
 		su := ldr.MakeSymbolUpdater(s)
@@ -150,13 +149,13 @@
 
 	case objabi.ElfRelocOffset + objabi.RelocType(elf.R_ARM_GOT_PREL): // GOT(nil) + A - nil
 		if targType != sym.SDYNIMPORT {
-			addgotsyminternal2(target, ldr, syms, targ)
+			addgotsyminternal(target, ldr, syms, targ)
 		} else {
-			addgotsym2(target, ldr, syms, targ)
+			ld.AddGotSym(target, ldr, syms, targ, uint32(elf.R_ARM_GLOB_DAT))
 		}
 		su := ldr.MakeSymbolUpdater(s)
 		su.SetRelocType(rIdx, objabi.R_PCREL)
-		su.SetRelocSym(rIdx, syms.GOT2)
+		su.SetRelocSym(rIdx, syms.GOT)
 		su.SetRelocAdd(rIdx, r.Add()+4+int64(ldr.SymGot(targ)))
 		return true
 
@@ -168,7 +167,7 @@
 	case objabi.ElfRelocOffset + objabi.RelocType(elf.R_ARM_GOTPC): // R_ARM_BASE_PREL
 		su := ldr.MakeSymbolUpdater(s)
 		su.SetRelocType(rIdx, objabi.R_PCREL)
-		su.SetRelocSym(rIdx, syms.GOT2)
+		su.SetRelocSym(rIdx, syms.GOT)
 		su.SetRelocAdd(rIdx, r.Add()+4)
 		return true
 
@@ -176,8 +175,8 @@
 		su := ldr.MakeSymbolUpdater(s)
 		su.SetRelocType(rIdx, objabi.R_CALLARM)
 		if targType == sym.SDYNIMPORT {
-			addpltsym2(target, ldr, syms, targ)
-			su.SetRelocSym(rIdx, syms.PLT2)
+			addpltsym(target, ldr, syms, targ)
+			su.SetRelocSym(rIdx, syms.PLT)
 			su.SetRelocAdd(rIdx, int64(braddoff(int32(r.Add()), ldr.SymPlt(targ)/4)))
 		}
 		return true
@@ -201,8 +200,8 @@
 		su := ldr.MakeSymbolUpdater(s)
 		su.SetRelocType(rIdx, objabi.R_CALLARM)
 		if targType == sym.SDYNIMPORT {
-			addpltsym2(target, ldr, syms, targ)
-			su.SetRelocSym(rIdx, syms.PLT2)
+			addpltsym(target, ldr, syms, targ)
+			su.SetRelocSym(rIdx, syms.PLT)
 			su.SetRelocAdd(rIdx, int64(braddoff(int32(r.Add()), ldr.SymPlt(targ)/4)))
 		}
 
@@ -224,9 +223,9 @@
 			// External linker will do this relocation.
 			return true
 		}
-		addpltsym2(target, ldr, syms, targ)
+		addpltsym(target, ldr, syms, targ)
 		su := ldr.MakeSymbolUpdater(s)
-		su.SetRelocSym(rIdx, syms.PLT2)
+		su.SetRelocSym(rIdx, syms.PLT)
 		su.SetRelocAdd(rIdx, int64(ldr.SymPlt(targ)))
 		return true
 
@@ -235,8 +234,8 @@
 			break
 		}
 		if target.IsElf() {
-			ld.Adddynsym2(ldr, target, syms, targ)
-			rel := ldr.MakeSymbolUpdater(syms.Rel2)
+			ld.Adddynsym(ldr, target, syms, targ)
+			rel := ldr.MakeSymbolUpdater(syms.Rel)
 			rel.AddAddrPlus(target.Arch, s, int64(r.Off()))
 			rel.AddUint32(target.Arch, ld.ELF32_R_INFO(uint32(ldr.SymDynid(targ)), uint32(elf.R_ARM_GLOB_DAT))) // we need a nil + A dynamic reloc
 			su := ldr.MakeSymbolUpdater(s)
@@ -249,28 +248,29 @@
 	return false
 }
 
-func elfreloc1(ctxt *ld.Link, r *sym.Reloc, sectoff int64) bool {
+func elfreloc1(ctxt *ld.Link, ldr *loader.Loader, s loader.Sym, r loader.ExtRelocView, sectoff int64) bool {
 	ctxt.Out.Write32(uint32(sectoff))
 
 	elfsym := ld.ElfSymForReloc(ctxt, r.Xsym)
-	switch r.Type {
+	siz := r.Siz()
+	switch r.Type() {
 	default:
 		return false
 	case objabi.R_ADDR, objabi.R_DWARFSECREF:
-		if r.Siz == 4 {
+		if siz == 4 {
 			ctxt.Out.Write32(uint32(elf.R_ARM_ABS32) | uint32(elfsym)<<8)
 		} else {
 			return false
 		}
 	case objabi.R_PCREL:
-		if r.Siz == 4 {
+		if siz == 4 {
 			ctxt.Out.Write32(uint32(elf.R_ARM_REL32) | uint32(elfsym)<<8)
 		} else {
 			return false
 		}
 	case objabi.R_CALLARM:
-		if r.Siz == 4 {
-			if r.Add&0xff000000 == 0xeb000000 { // BL
+		if siz == 4 {
+			if r.Add()&0xff000000 == 0xeb000000 { // BL
 				ctxt.Out.Write32(uint32(elf.R_ARM_CALL) | uint32(elfsym)<<8)
 			} else {
 				ctxt.Out.Write32(uint32(elf.R_ARM_JUMP24) | uint32(elfsym)<<8)
@@ -283,7 +283,7 @@
 	case objabi.R_TLS_IE:
 		ctxt.Out.Write32(uint32(elf.R_ARM_TLS_IE32) | uint32(elfsym)<<8)
 	case objabi.R_GOTPCREL:
-		if r.Siz == 4 {
+		if siz == 4 {
 			ctxt.Out.Write32(uint32(elf.R_ARM_GOT_PREL) | uint32(elfsym)<<8)
 		} else {
 			return false
@@ -318,23 +318,24 @@
 	}
 }
 
-func machoreloc1(arch *sys.Arch, out *ld.OutBuf, s *sym.Symbol, r *sym.Reloc, sectoff int64) bool {
+func machoreloc1(*sys.Arch, *ld.OutBuf, *loader.Loader, loader.Sym, loader.ExtRelocView, int64) bool {
 	return false
 }
 
-func pereloc1(arch *sys.Arch, out *ld.OutBuf, s *sym.Symbol, r *sym.Reloc, sectoff int64) bool {
+func pereloc1(arch *sys.Arch, out *ld.OutBuf, ldr *loader.Loader, s loader.Sym, r loader.ExtRelocView, sectoff int64) bool {
 	rs := r.Xsym
+	rt := r.Type()
 
-	if rs.Dynid < 0 {
-		ld.Errorf(s, "reloc %d (%s) to non-coff symbol %s type=%d (%s)", r.Type, sym.RelocName(arch, r.Type), rs.Name, rs.Type, rs.Type)
+	if ldr.SymDynid(rs) < 0 {
+		ldr.Errorf(s, "reloc %d (%s) to non-coff symbol %s type=%d (%s)", rt, sym.RelocName(arch, rt), ldr.SymName(rs), ldr.SymType(rs), ldr.SymType(rs))
 		return false
 	}
 
 	out.Write32(uint32(sectoff))
-	out.Write32(uint32(rs.Dynid))
+	out.Write32(uint32(ldr.SymDynid(rs)))
 
 	var v uint32
-	switch r.Type {
+	switch rt {
 	default:
 		// unsupported relocation type
 		return false
@@ -526,82 +527,66 @@
 	tramp.AddReloc(r)
 }
 
-func archreloc(target *ld.Target, syms *ld.ArchSyms, r *sym.Reloc, s *sym.Symbol, val int64) (int64, bool) {
+func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loader.Reloc2, rr *loader.ExtReloc, s loader.Sym, val int64) (o int64, needExtReloc bool, ok bool) {
+	rs := r.Sym()
+	rs = ldr.ResolveABIAlias(rs)
 	if target.IsExternal() {
-		switch r.Type {
+		switch r.Type() {
 		case objabi.R_CALLARM:
-			r.Done = false
-
 			// set up addend for eventual relocation via outer symbol.
-			rs := r.Sym
+			rs, off := ld.FoldSubSymbolOffset(ldr, rs)
+			rr.Xadd = int64(signext24(r.Add() & 0xffffff))
+			rr.Xadd *= 4
+			rr.Xadd += off
+			rst := ldr.SymType(rs)
+			if rst != sym.SHOSTOBJ && rst != sym.SDYNIMPORT && rst != sym.SUNDEFEXT && ldr.SymSect(rs) == nil {
+				ldr.Errorf(s, "missing section for %s", ldr.SymName(rs))
+			}
+			rr.Xsym = rs
 
-			r.Xadd = int64(signext24(r.Add & 0xffffff))
-			r.Xadd *= 4
-			for rs.Outer != nil {
-				r.Xadd += ld.Symaddr(rs) - ld.Symaddr(rs.Outer)
-				rs = rs.Outer
+			if rr.Xadd/4 > 0x7fffff || rr.Xadd/4 < -0x800000 {
+				ldr.Errorf(s, "direct call too far %d", rr.Xadd/4)
 			}
 
-			if rs.Type != sym.SHOSTOBJ && rs.Type != sym.SDYNIMPORT && rs.Type != sym.SUNDEFEXT && rs.Sect == nil {
-				ld.Errorf(s, "missing section for %s", rs.Name)
-			}
-			r.Xsym = rs
-
-			// ld64 for arm seems to want the symbol table to contain offset
-			// into the section rather than pseudo virtual address that contains
-			// the section load address.
-			// we need to compensate that by removing the instruction's address
-			// from addend.
-			if target.IsDarwin() {
-				r.Xadd -= ld.Symaddr(s) + int64(r.Off)
-			}
-
-			if r.Xadd/4 > 0x7fffff || r.Xadd/4 < -0x800000 {
-				ld.Errorf(s, "direct call too far %d", r.Xadd/4)
-			}
-
-			return int64(braddoff(int32(0xff000000&uint32(r.Add)), int32(0xffffff&uint32(r.Xadd/4)))), true
+			return int64(braddoff(int32(0xff000000&uint32(r.Add())), int32(0xffffff&uint32(rr.Xadd/4)))), true, true
 		}
 
-		return -1, false
+		return -1, false, false
 	}
 
-	switch r.Type {
-	case objabi.R_CONST:
-		return r.Add, true
-	case objabi.R_GOTOFF:
-		return ld.Symaddr(r.Sym) + r.Add - ld.Symaddr(syms.GOT), true
-
+	const isOk = true
+	const noExtReloc = false
+	switch r.Type() {
 	// The following three arch specific relocations are only for generation of
 	// Linux/ARM ELF's PLT entry (3 assembler instruction)
 	case objabi.R_PLT0: // add ip, pc, #0xXX00000
-		if ld.Symaddr(syms.GOTPLT) < ld.Symaddr(syms.PLT) {
-			ld.Errorf(s, ".got.plt should be placed after .plt section.")
+		if ldr.SymValue(syms.GOTPLT) < ldr.SymValue(syms.PLT) {
+			ldr.Errorf(s, ".got.plt should be placed after .plt section.")
 		}
-		return 0xe28fc600 + (0xff & (int64(uint32(ld.Symaddr(r.Sym)-(ld.Symaddr(syms.PLT)+int64(r.Off))+r.Add)) >> 20)), true
+		return 0xe28fc600 + (0xff & (int64(uint32(ldr.SymValue(rs)-(ldr.SymValue(syms.PLT)+int64(r.Off()))+r.Add())) >> 20)), noExtReloc, isOk
 	case objabi.R_PLT1: // add ip, ip, #0xYY000
-		return 0xe28cca00 + (0xff & (int64(uint32(ld.Symaddr(r.Sym)-(ld.Symaddr(syms.PLT)+int64(r.Off))+r.Add+4)) >> 12)), true
+		return 0xe28cca00 + (0xff & (int64(uint32(ldr.SymValue(rs)-(ldr.SymValue(syms.PLT)+int64(r.Off()))+r.Add()+4)) >> 12)), noExtReloc, isOk
 	case objabi.R_PLT2: // ldr pc, [ip, #0xZZZ]!
-		return 0xe5bcf000 + (0xfff & int64(uint32(ld.Symaddr(r.Sym)-(ld.Symaddr(syms.PLT)+int64(r.Off))+r.Add+8))), true
+		return 0xe5bcf000 + (0xfff & int64(uint32(ldr.SymValue(rs)-(ldr.SymValue(syms.PLT)+int64(r.Off()))+r.Add()+8))), noExtReloc, isOk
 	case objabi.R_CALLARM: // bl XXXXXX or b YYYYYY
 		// r.Add is the instruction
 		// low 24-bit encodes the target address
-		t := (ld.Symaddr(r.Sym) + int64(signext24(r.Add&0xffffff)*4) - (s.Value + int64(r.Off))) / 4
+		t := (ldr.SymValue(rs) + int64(signext24(r.Add()&0xffffff)*4) - (ldr.SymValue(s) + int64(r.Off()))) / 4
 		if t > 0x7fffff || t < -0x800000 {
-			ld.Errorf(s, "direct call too far: %s %x", r.Sym.Name, t)
+			ldr.Errorf(s, "direct call too far: %s %x", ldr.SymName(rs), t)
 		}
-		return int64(braddoff(int32(0xff000000&uint32(r.Add)), int32(0xffffff&t))), true
+		return int64(braddoff(int32(0xff000000&uint32(r.Add())), int32(0xffffff&t))), noExtReloc, isOk
 	}
 
-	return val, false
+	return val, false, false
 }
 
-func archrelocvariant(target *ld.Target, syms *ld.ArchSyms, r *sym.Reloc, s *sym.Symbol, t int64) int64 {
+func archrelocvariant(*ld.Target, *loader.Loader, loader.Reloc2, sym.RelocVariant, loader.Sym, int64) int64 {
 	log.Fatalf("unexpected relocation variant")
-	return t
+	return -1
 }
 
-func addpltreloc2(ldr *loader.Loader, plt *loader.SymbolBuilder, got *loader.SymbolBuilder, s loader.Sym, typ objabi.RelocType) {
+func addpltreloc(ldr *loader.Loader, plt *loader.SymbolBuilder, got *loader.SymbolBuilder, s loader.Sym, typ objabi.RelocType) {
 	r, _ := plt.AddRel(typ)
 	r.SetSym(got.Sym())
 	r.SetOff(int32(plt.Size()))
@@ -613,17 +598,17 @@
 	plt.Grow(plt.Size())
 }
 
-func addpltsym2(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym) {
+func addpltsym(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym) {
 	if ldr.SymPlt(s) >= 0 {
 		return
 	}
 
-	ld.Adddynsym2(ldr, target, syms, s)
+	ld.Adddynsym(ldr, target, syms, s)
 
 	if target.IsElf() {
-		plt := ldr.MakeSymbolUpdater(syms.PLT2)
-		got := ldr.MakeSymbolUpdater(syms.GOTPLT2)
-		rel := ldr.MakeSymbolUpdater(syms.RelPLT2)
+		plt := ldr.MakeSymbolUpdater(syms.PLT)
+		got := ldr.MakeSymbolUpdater(syms.GOTPLT)
+		rel := ldr.MakeSymbolUpdater(syms.RelPLT)
 		if plt.Size() == 0 {
 			panic("plt is not set up")
 		}
@@ -639,9 +624,9 @@
 		// .plt entry, this depends on the .got entry
 		ldr.SetPlt(s, int32(plt.Size()))
 
-		addpltreloc2(ldr, plt, got, s, objabi.R_PLT0) // add lr, pc, #0xXX00000
-		addpltreloc2(ldr, plt, got, s, objabi.R_PLT1) // add lr, lr, #0xYY000
-		addpltreloc2(ldr, plt, got, s, objabi.R_PLT2) // ldr pc, [lr, #0xZZZ]!
+		addpltreloc(ldr, plt, got, s, objabi.R_PLT0) // add lr, pc, #0xXX00000
+		addpltreloc(ldr, plt, got, s, objabi.R_PLT1) // add lr, lr, #0xYY000
+		addpltreloc(ldr, plt, got, s, objabi.R_PLT2) // ldr pc, [lr, #0xZZZ]!
 
 		// rel
 		rel.AddAddrPlus(target.Arch, got.Sym(), int64(ldr.SymGot(s)))
@@ -652,12 +637,12 @@
 	}
 }
 
-func addgotsyminternal2(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym) {
+func addgotsyminternal(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym) {
 	if ldr.SymGot(s) >= 0 {
 		return
 	}
 
-	got := ldr.MakeSymbolUpdater(syms.GOT2)
+	got := ldr.MakeSymbolUpdater(syms.GOT)
 	ldr.SetGot(s, int32(got.Size()))
 	got.AddAddrPlus(target.Arch, s, 0)
 
@@ -666,133 +651,3 @@
 		ldr.Errorf(s, "addgotsyminternal: unsupported binary format")
 	}
 }
-
-func addgotsym2(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym) {
-	if ldr.SymGot(s) >= 0 {
-		return
-	}
-
-	ld.Adddynsym2(ldr, target, syms, s)
-	got := ldr.MakeSymbolUpdater(syms.GOT2)
-	ldr.SetGot(s, int32(got.Size()))
-	got.AddUint64(target.Arch, 0)
-
-	if target.IsElf() {
-		rel := ldr.MakeSymbolUpdater(syms.Rel2)
-		rel.AddAddrPlus(target.Arch, got.Sym(), int64(ldr.SymGot(s)))
-		rel.AddUint32(target.Arch, ld.ELF32_R_INFO(uint32(ldr.SymDynid(s)), uint32(elf.R_ARM_GLOB_DAT)))
-	} else {
-		ldr.Errorf(s, "addgotsym: unsupported binary format")
-	}
-}
-
-func asmb(ctxt *ld.Link, _ *loader.Loader) {
-	if ctxt.IsELF {
-		ld.Asmbelfsetup()
-	}
-
-	var wg sync.WaitGroup
-	sect := ld.Segtext.Sections[0]
-	offset := sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff
-	ld.WriteParallel(&wg, ld.Codeblk, ctxt, offset, sect.Vaddr, sect.Length)
-
-	for _, sect := range ld.Segtext.Sections[1:] {
-		offset := sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff
-		ld.WriteParallel(&wg, ld.Datblk, ctxt, offset, sect.Vaddr, sect.Length)
-	}
-
-	if ld.Segrodata.Filelen > 0 {
-		ld.WriteParallel(&wg, ld.Datblk, ctxt, ld.Segrodata.Fileoff, ld.Segrodata.Vaddr, ld.Segrodata.Filelen)
-	}
-
-	if ld.Segrelrodata.Filelen > 0 {
-		ld.WriteParallel(&wg, ld.Datblk, ctxt, ld.Segrelrodata.Fileoff, ld.Segrelrodata.Vaddr, ld.Segrelrodata.Filelen)
-	}
-
-	ld.WriteParallel(&wg, ld.Datblk, ctxt, ld.Segdata.Fileoff, ld.Segdata.Vaddr, ld.Segdata.Filelen)
-
-	ld.WriteParallel(&wg, ld.Dwarfblk, ctxt, ld.Segdwarf.Fileoff, ld.Segdwarf.Vaddr, ld.Segdwarf.Filelen)
-	wg.Wait()
-}
-
-func asmb2(ctxt *ld.Link) {
-	/* output symbol table */
-	ld.Symsize = 0
-
-	ld.Lcsize = 0
-	symo := uint32(0)
-	if !*ld.FlagS {
-		// TODO: rationalize
-		switch ctxt.HeadType {
-		default:
-			if ctxt.IsELF {
-				symo = uint32(ld.Segdwarf.Fileoff + ld.Segdwarf.Filelen)
-				symo = uint32(ld.Rnd(int64(symo), int64(*ld.FlagRound)))
-			}
-
-		case objabi.Hplan9:
-			symo = uint32(ld.Segdata.Fileoff + ld.Segdata.Filelen)
-
-		case objabi.Hwindows:
-			symo = uint32(ld.Segdwarf.Fileoff + ld.Segdwarf.Filelen)
-			symo = uint32(ld.Rnd(int64(symo), ld.PEFILEALIGN))
-		}
-
-		ctxt.Out.SeekSet(int64(symo))
-		switch ctxt.HeadType {
-		default:
-			if ctxt.IsELF {
-				ld.Asmelfsym(ctxt)
-				ctxt.Out.Write(ld.Elfstrdat)
-
-				if ctxt.LinkMode == ld.LinkExternal {
-					ld.Elfemitreloc(ctxt)
-				}
-			}
-
-		case objabi.Hplan9:
-			ld.Asmplan9sym(ctxt)
-
-			sym := ctxt.Syms.Lookup("pclntab", 0)
-			if sym != nil {
-				ld.Lcsize = int32(len(sym.P))
-				ctxt.Out.Write(sym.P)
-			}
-
-		case objabi.Hwindows:
-			// Do nothing
-		}
-	}
-
-	ctxt.Out.SeekSet(0)
-	switch ctxt.HeadType {
-	default:
-	case objabi.Hplan9: /* plan 9 */
-		ctxt.Out.Write32b(0x647)                      /* magic */
-		ctxt.Out.Write32b(uint32(ld.Segtext.Filelen)) /* sizes */
-		ctxt.Out.Write32b(uint32(ld.Segdata.Filelen))
-		ctxt.Out.Write32b(uint32(ld.Segdata.Length - ld.Segdata.Filelen))
-		ctxt.Out.Write32b(uint32(ld.Symsize))          /* nsyms */
-		ctxt.Out.Write32b(uint32(ld.Entryvalue(ctxt))) /* va of entry */
-		ctxt.Out.Write32b(0)
-		ctxt.Out.Write32b(uint32(ld.Lcsize))
-
-	case objabi.Hlinux,
-		objabi.Hfreebsd,
-		objabi.Hnetbsd,
-		objabi.Hopenbsd:
-		ld.Asmbelf(ctxt, int64(symo))
-
-	case objabi.Hwindows:
-		ld.Asmbpe(ctxt)
-	}
-
-	if *ld.FlagC {
-		fmt.Printf("textsize=%d\n", ld.Segtext.Filelen)
-		fmt.Printf("datsize=%d\n", ld.Segdata.Filelen)
-		fmt.Printf("bsssize=%d\n", ld.Segdata.Length-ld.Segdata.Filelen)
-		fmt.Printf("symsize=%d\n", ld.Symsize)
-		fmt.Printf("lcsize=%d\n", ld.Lcsize)
-		fmt.Printf("total=%d\n", ld.Segtext.Filelen+ld.Segdata.Length+uint64(ld.Symsize)+uint64(ld.Lcsize))
-	}
-}
diff --git a/src/cmd/link/internal/arm/obj.go b/src/cmd/link/internal/arm/obj.go
index 47bc053..1a57298 100644
--- a/src/cmd/link/internal/arm/obj.go
+++ b/src/cmd/link/internal/arm/obj.go
@@ -46,16 +46,16 @@
 		Dwarfregsp: dwarfRegSP,
 		Dwarfreglr: dwarfRegLR,
 
-		Adddynrel2:       adddynrel2,
+		Plan9Magic: 0x647,
+
+		Adddynrel:        adddynrel,
 		Archinit:         archinit,
 		Archreloc:        archreloc,
 		Archrelocvariant: archrelocvariant,
 		Trampoline:       trampoline,
-		Asmb:             asmb,
-		Asmb2:            asmb2,
 		Elfreloc1:        elfreloc1,
 		Elfsetupplt:      elfsetupplt,
-		Gentext2:         gentext2,
+		Gentext:          gentext,
 		Machoreloc1:      machoreloc1,
 		PEreloc1:         pereloc1,
 
diff --git a/src/cmd/link/internal/arm64/asm.go b/src/cmd/link/internal/arm64/asm.go
index 417e4b1..bb23071 100644
--- a/src/cmd/link/internal/arm64/asm.go
+++ b/src/cmd/link/internal/arm64/asm.go
@@ -37,12 +37,10 @@
 	"cmd/link/internal/loader"
 	"cmd/link/internal/sym"
 	"debug/elf"
-	"fmt"
 	"log"
-	"sync"
 )
 
-func gentext2(ctxt *ld.Link, ldr *loader.Loader) {
+func gentext(ctxt *ld.Link, ldr *loader.Loader) {
 	initfunc, addmoduledata := ld.PrepareAddmoduledata(ctxt)
 	if initfunc == nil {
 		return
@@ -62,7 +60,7 @@
 		Off:  0,
 		Size: 8,
 		Type: objabi.R_ADDRARM64,
-		Sym:  ctxt.Moduledata2,
+		Sym:  ctxt.Moduledata,
 	}
 	initfunc.AddReloc(rel)
 
@@ -78,7 +76,7 @@
 	initfunc.AddReloc(rel2)
 }
 
-func adddynrel2(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym, r loader.Reloc2, rIdx int) bool {
+func adddynrel(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym, r loader.Reloc2, rIdx int) bool {
 
 	targ := r.Sym()
 	var targType sym.SymKind
@@ -123,9 +121,9 @@
 	case objabi.ElfRelocOffset + objabi.RelocType(elf.R_AARCH64_CALL26),
 		objabi.ElfRelocOffset + objabi.RelocType(elf.R_AARCH64_JUMP26):
 		if targType == sym.SDYNIMPORT {
-			addpltsym2(target, ldr, syms, targ)
+			addpltsym(target, ldr, syms, targ)
 			su := ldr.MakeSymbolUpdater(s)
-			su.SetRelocSym(rIdx, syms.PLT2)
+			su.SetRelocSym(rIdx, syms.PLT)
 			su.SetRelocAdd(rIdx, r.Add()+int64(ldr.SymPlt(targ)))
 		}
 		if (targType == 0 || targType == sym.SXREF) && !ldr.AttrVisibilityHidden(targ) {
@@ -144,10 +142,10 @@
 
 		// fall back to using GOT
 		// TODO: just needs relocation, no need to put in .dynsym
-		addgotsym2(target, ldr, syms, targ)
+		ld.AddGotSym(target, ldr, syms, targ, uint32(elf.R_AARCH64_GLOB_DAT))
 		su := ldr.MakeSymbolUpdater(s)
 		su.SetRelocType(rIdx, objabi.R_ARM64_GOT)
-		su.SetRelocSym(rIdx, syms.GOT2)
+		su.SetRelocSym(rIdx, syms.GOT)
 		su.SetRelocAdd(rIdx, r.Add()+int64(ldr.SymGot(targ)))
 		return true
 
@@ -233,9 +231,9 @@
 			// The code is asking for the address of an external
 			// function. We provide it with the address of the
 			// correspondent GOT symbol.
-			addgotsym2(target, ldr, syms, targ)
+			ld.AddGotSym(target, ldr, syms, targ, uint32(elf.R_AARCH64_GLOB_DAT))
 			su := ldr.MakeSymbolUpdater(s)
-			su.SetRelocSym(rIdx, syms.GOT2)
+			su.SetRelocSym(rIdx, syms.GOT)
 			su.SetRelocAdd(rIdx, r.Add()+int64(ldr.SymGot(targ)))
 			return true
 		}
@@ -307,7 +305,7 @@
 			// AddAddrPlus is used for r_offset and r_addend to
 			// generate new R_ADDR relocations that will update
 			// these fields in the 'reloc' phase.
-			rela := ldr.MakeSymbolUpdater(syms.Rela2)
+			rela := ldr.MakeSymbolUpdater(syms.Rela)
 			rela.AddAddrPlus(target.Arch, s, int64(r.Off()))
 			if r.Siz() == 8 {
 				rela.AddUint64(target.Arch, ld.ELF64_R_INFO(0, uint32(elf.R_AARCH64_RELATIVE)))
@@ -325,15 +323,16 @@
 	return false
 }
 
-func elfreloc1(ctxt *ld.Link, r *sym.Reloc, sectoff int64) bool {
+func elfreloc1(ctxt *ld.Link, ldr *loader.Loader, s loader.Sym, r loader.ExtRelocView, sectoff int64) bool {
 	ctxt.Out.Write64(uint64(sectoff))
 
 	elfsym := ld.ElfSymForReloc(ctxt, r.Xsym)
-	switch r.Type {
+	siz := r.Siz()
+	switch r.Type() {
 	default:
 		return false
 	case objabi.R_ADDR, objabi.R_DWARFSECREF:
-		switch r.Siz {
+		switch siz {
 		case 4:
 			ctxt.Out.Write64(uint64(elf.R_AARCH64_ABS32) | uint64(elfsym)<<32)
 		case 8:
@@ -360,7 +359,7 @@
 		ctxt.Out.Write64(uint64(sectoff + 4))
 		ctxt.Out.Write64(uint64(elf.R_AARCH64_LD64_GOT_LO12_NC) | uint64(elfsym)<<32)
 	case objabi.R_CALLARM64:
-		if r.Siz != 4 {
+		if siz != 4 {
 			return false
 		}
 		ctxt.Out.Write64(uint64(elf.R_AARCH64_CALL26) | uint64(elfsym)<<32)
@@ -371,41 +370,43 @@
 	return true
 }
 
-func machoreloc1(arch *sys.Arch, out *ld.OutBuf, s *sym.Symbol, r *sym.Reloc, sectoff int64) bool {
+func machoreloc1(arch *sys.Arch, out *ld.OutBuf, ldr *loader.Loader, s loader.Sym, r loader.ExtRelocView, sectoff int64) bool {
 	var v uint32
 
 	rs := r.Xsym
+	rt := r.Type()
+	siz := r.Siz()
 
-	if rs.Type == sym.SHOSTOBJ || r.Type == objabi.R_CALLARM64 || r.Type == objabi.R_ADDRARM64 {
-		if rs.Dynid < 0 {
-			ld.Errorf(s, "reloc %d (%s) to non-macho symbol %s type=%d (%s)", r.Type, sym.RelocName(arch, r.Type), rs.Name, rs.Type, rs.Type)
+	if ldr.SymType(rs) == sym.SHOSTOBJ || rt == objabi.R_CALLARM64 || rt == objabi.R_ADDRARM64 {
+		if ldr.SymDynid(rs) < 0 {
+			ldr.Errorf(s, "reloc %d (%s) to non-macho symbol %s type=%d (%s)", rt, sym.RelocName(arch, rt), ldr.SymName(rs), ldr.SymType(rs), ldr.SymType(rs))
 			return false
 		}
 
-		v = uint32(rs.Dynid)
+		v = uint32(ldr.SymDynid(rs))
 		v |= 1 << 27 // external relocation
 	} else {
-		v = uint32(rs.Sect.Extnum)
+		v = uint32(ldr.SymSect(rs).Extnum)
 		if v == 0 {
-			ld.Errorf(s, "reloc %d (%s) to symbol %s in non-macho section %s type=%d (%s)", r.Type, sym.RelocName(arch, r.Type), rs.Name, rs.Sect.Name, rs.Type, rs.Type)
+			ldr.Errorf(s, "reloc %d (%s) to symbol %s in non-macho section %s type=%d (%s)", rt, sym.RelocName(arch, rt), ldr.SymName(rs), ldr.SymSect(rs).Name, ldr.SymType(rs), ldr.SymType(rs))
 			return false
 		}
 	}
 
-	switch r.Type {
+	switch rt {
 	default:
 		return false
 	case objabi.R_ADDR:
 		v |= ld.MACHO_ARM64_RELOC_UNSIGNED << 28
 	case objabi.R_CALLARM64:
 		if r.Xadd != 0 {
-			ld.Errorf(s, "ld64 doesn't allow BR26 reloc with non-zero addend: %s+%d", rs.Name, r.Xadd)
+			ldr.Errorf(s, "ld64 doesn't allow BR26 reloc with non-zero addend: %s+%d", ldr.SymName(rs), r.Xadd)
 		}
 
 		v |= 1 << 24 // pc-relative bit
 		v |= ld.MACHO_ARM64_RELOC_BRANCH26 << 28
 	case objabi.R_ADDRARM64:
-		r.Siz = 4
+		siz = 4
 		// Two relocation entries: MACHO_ARM64_RELOC_PAGEOFF12 MACHO_ARM64_RELOC_PAGE21
 		// if r.Xadd is non-zero, add two MACHO_ARM64_RELOC_ADDEND.
 		if r.Xadd != 0 {
@@ -422,7 +423,7 @@
 		v |= ld.MACHO_ARM64_RELOC_PAGE21 << 28
 	}
 
-	switch r.Siz {
+	switch siz {
 	default:
 		return false
 	case 1:
@@ -440,56 +441,26 @@
 	return true
 }
 
-func archreloc(target *ld.Target, syms *ld.ArchSyms, r *sym.Reloc, s *sym.Symbol, val int64) (int64, bool) {
+func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loader.Reloc2, rr *loader.ExtReloc, s loader.Sym, val int64) (int64, bool, bool) {
+	const extRelocNeeded = true
+	const extRelocNotNeeded = false
+	const isOk = true
+
+	rs := ldr.ResolveABIAlias(r.Sym())
+
 	if target.IsExternal() {
-		switch r.Type {
+		switch r.Type() {
 		default:
-			return val, false
-		case objabi.R_ARM64_GOTPCREL:
-			var o1, o2 uint32
-			if target.IsBigEndian() {
-				o1 = uint32(val >> 32)
-				o2 = uint32(val)
-			} else {
-				o1 = uint32(val)
-				o2 = uint32(val >> 32)
-			}
-			// Any relocation against a function symbol is redirected to
-			// be against a local symbol instead (see putelfsym in
-			// symtab.go) but unfortunately the system linker was buggy
-			// when confronted with a R_AARCH64_ADR_GOT_PAGE relocation
-			// against a local symbol until May 2015
-			// (https://sourceware.org/bugzilla/show_bug.cgi?id=18270). So
-			// we convert the adrp; ld64 + R_ARM64_GOTPCREL into adrp;
-			// add + R_ADDRARM64.
-			if !(r.Sym.IsFileLocal() || r.Sym.Attr.VisibilityHidden() || r.Sym.Attr.Local()) && r.Sym.Type == sym.STEXT && target.IsDynlinkingGo() {
-				if o2&0xffc00000 != 0xf9400000 {
-					ld.Errorf(s, "R_ARM64_GOTPCREL against unexpected instruction %x", o2)
-				}
-				o2 = 0x91000000 | (o2 & 0x000003ff)
-				r.Type = objabi.R_ADDRARM64
-			}
-			if target.IsBigEndian() {
-				val = int64(o1)<<32 | int64(o2)
-			} else {
-				val = int64(o2)<<32 | int64(o1)
-			}
-			fallthrough
-		case objabi.R_ADDRARM64:
-			r.Done = false
-
+		case objabi.R_ARM64_GOTPCREL,
+			objabi.R_ADDRARM64:
 			// set up addend for eventual relocation via outer symbol.
-			rs := r.Sym
-			r.Xadd = r.Add
-			for rs.Outer != nil {
-				r.Xadd += ld.Symaddr(rs) - ld.Symaddr(rs.Outer)
-				rs = rs.Outer
+			rs, off := ld.FoldSubSymbolOffset(ldr, rs)
+			rr.Xadd = r.Add() + off
+			rst := ldr.SymType(rs)
+			if rst != sym.SHOSTOBJ && rst != sym.SDYNIMPORT && ldr.SymSect(rs) == nil {
+				ldr.Errorf(s, "missing section for %s", ldr.SymName(rs))
 			}
-
-			if rs.Type != sym.SHOSTOBJ && rs.Type != sym.SDYNIMPORT && rs.Sect == nil {
-				ld.Errorf(s, "missing section for %s", rs.Name)
-			}
-			r.Xsym = rs
+			rr.Xsym = rs
 
 			// Note: ld64 currently has a bug that any non-zero addend for BR26 relocation
 			// will make the linking fail because it thinks the code is not PIC even though
@@ -511,9 +482,9 @@
 				// can only encode 24-bit of signed addend, but the instructions
 				// supports 33-bit of signed addend, so we always encode the
 				// addend in place.
-				o0 |= (uint32((r.Xadd>>12)&3) << 29) | (uint32((r.Xadd>>12>>2)&0x7ffff) << 5)
-				o1 |= uint32(r.Xadd&0xfff) << 10
-				r.Xadd = 0
+				o0 |= (uint32((rr.Xadd>>12)&3) << 29) | (uint32((rr.Xadd>>12>>2)&0x7ffff) << 5)
+				o1 |= uint32(rr.Xadd&0xfff) << 10
+				rr.Xadd = 0
 
 				// when laid out, the instruction order must always be o1, o2.
 				if target.IsBigEndian() {
@@ -523,28 +494,21 @@
 				}
 			}
 
-			return val, true
+			return val, extRelocNeeded, isOk
 		case objabi.R_CALLARM64,
 			objabi.R_ARM64_TLS_LE,
 			objabi.R_ARM64_TLS_IE:
-			r.Done = false
-			r.Xsym = r.Sym
-			r.Xadd = r.Add
-			return val, true
+			rr.Xsym = rs
+			rr.Xadd = r.Add()
+			return val, extRelocNeeded, isOk
 		}
 	}
 
-	switch r.Type {
-	case objabi.R_CONST:
-		return r.Add, true
-
-	case objabi.R_GOTOFF:
-		return ld.Symaddr(r.Sym) + r.Add - ld.Symaddr(syms.GOT), true
-
+	switch r.Type() {
 	case objabi.R_ADDRARM64:
-		t := ld.Symaddr(r.Sym) + r.Add - ((s.Value + int64(r.Off)) &^ 0xfff)
+		t := ldr.SymAddr(rs) + r.Add() - ((ldr.SymValue(s) + int64(r.Off())) &^ 0xfff)
 		if t >= 1<<32 || t < -1<<32 {
-			ld.Errorf(s, "program too large, address relocation distance = %d", t)
+			ldr.Errorf(s, "program too large, address relocation distance = %d", t)
 		}
 
 		var o0, o1 uint32
@@ -562,37 +526,36 @@
 
 		// when laid out, the instruction order must always be o1, o2.
 		if target.IsBigEndian() {
-			return int64(o0)<<32 | int64(o1), true
+			return int64(o0)<<32 | int64(o1), extRelocNotNeeded, true
 		}
-		return int64(o1)<<32 | int64(o0), true
+		return int64(o1)<<32 | int64(o0), extRelocNotNeeded, true
 
 	case objabi.R_ARM64_TLS_LE:
-		r.Done = false
 		if target.IsDarwin() {
-			ld.Errorf(s, "TLS reloc on unsupported OS %v", target.HeadType)
+			ldr.Errorf(s, "TLS reloc on unsupported OS %v", target.HeadType)
 		}
 		// The TCB is two pointers. This is not documented anywhere, but is
 		// de facto part of the ABI.
-		v := r.Sym.Value + int64(2*target.Arch.PtrSize)
+		v := ldr.SymValue(rs) + int64(2*target.Arch.PtrSize)
 		if v < 0 || v >= 32678 {
-			ld.Errorf(s, "TLS offset out of range %d", v)
+			ldr.Errorf(s, "TLS offset out of range %d", v)
 		}
-		return val | (v << 5), true
+		return val | (v << 5), extRelocNeeded, true
 
 	case objabi.R_ARM64_TLS_IE:
 		if target.IsPIE() && target.IsElf() {
 			// We are linking the final executable, so we
 			// can optimize any TLS IE relocation to LE.
-			r.Done = false
+
 			if !target.IsLinux() {
-				ld.Errorf(s, "TLS reloc on unsupported OS %v", target.HeadType)
+				ldr.Errorf(s, "TLS reloc on unsupported OS %v", target.HeadType)
 			}
 
 			// The TCB is two pointers. This is not documented anywhere, but is
 			// de facto part of the ABI.
-			v := ld.Symaddr(r.Sym) + int64(2*target.Arch.PtrSize) + r.Add
+			v := ldr.SymAddr(rs) + int64(2*target.Arch.PtrSize) + r.Add()
 			if v < 0 || v >= 32678 {
-				ld.Errorf(s, "TLS offset out of range %d", v)
+				ldr.Errorf(s, "TLS offset out of range %d", v)
 			}
 
 			var o0, o1 uint32
@@ -610,110 +573,112 @@
 			// R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC
 			// turn LD64 to MOVK
 			if v&3 != 0 {
-				ld.Errorf(s, "invalid address: %x for relocation type: R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC", v)
+				ldr.Errorf(s, "invalid address: %x for relocation type: R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC", v)
 			}
 			o1 = 0xf2800000 | uint32(o1&0x1f) | (uint32(v&0xffff) << 5)
 
 			// when laid out, the instruction order must always be o0, o1.
 			if target.IsBigEndian() {
-				return int64(o0)<<32 | int64(o1), true
+				return int64(o0)<<32 | int64(o1), extRelocNotNeeded, isOk
 			}
-			return int64(o1)<<32 | int64(o0), true
+			return int64(o1)<<32 | int64(o0), extRelocNotNeeded, isOk
 		} else {
-			log.Fatalf("cannot handle R_ARM64_TLS_IE (sym %s) when linking internally", s.Name)
+			log.Fatalf("cannot handle R_ARM64_TLS_IE (sym %s) when linking internally", ldr.SymName(s))
 		}
 
 	case objabi.R_CALLARM64:
 		var t int64
-		if r.Sym.Type == sym.SDYNIMPORT {
-			t = (ld.Symaddr(syms.PLT) + r.Add) - (s.Value + int64(r.Off))
+		if ldr.SymType(rs) == sym.SDYNIMPORT {
+			t = (ldr.SymAddr(syms.PLT) + r.Add()) - (ldr.SymValue(s) + int64(r.Off()))
 		} else {
-			t = (ld.Symaddr(r.Sym) + r.Add) - (s.Value + int64(r.Off))
+			t = (ldr.SymAddr(rs) + r.Add()) - (ldr.SymValue(s) + int64(r.Off()))
 		}
 		if t >= 1<<27 || t < -1<<27 {
-			ld.Errorf(s, "program too large, call relocation distance = %d", t)
+			ldr.Errorf(s, "program too large, call relocation distance = %d", t)
 		}
-		return val | ((t >> 2) & 0x03ffffff), true
+		return val | ((t >> 2) & 0x03ffffff), extRelocNotNeeded, true
 
 	case objabi.R_ARM64_GOT:
-		if s.P[r.Off+3]&0x9f == 0x90 {
+		sData := ldr.Data(s)
+		if sData[r.Off()+3]&0x9f == 0x90 {
 			// R_AARCH64_ADR_GOT_PAGE
 			// patch instruction: adrp
-			t := ld.Symaddr(r.Sym) + r.Add - ((s.Value + int64(r.Off)) &^ 0xfff)
+			t := ldr.SymAddr(rs) + r.Add() - ((ldr.SymValue(s) + int64(r.Off())) &^ 0xfff)
 			if t >= 1<<32 || t < -1<<32 {
-				ld.Errorf(s, "program too large, address relocation distance = %d", t)
+				ldr.Errorf(s, "program too large, address relocation distance = %d", t)
 			}
 			var o0 uint32
 			o0 |= (uint32((t>>12)&3) << 29) | (uint32((t>>12>>2)&0x7ffff) << 5)
-			return val | int64(o0), true
-		} else if s.P[r.Off+3] == 0xf9 {
+			return val | int64(o0), extRelocNotNeeded, isOk
+		} else if sData[r.Off()+3] == 0xf9 {
 			// R_AARCH64_LD64_GOT_LO12_NC
 			// patch instruction: ldr
-			t := ld.Symaddr(r.Sym) + r.Add - ((s.Value + int64(r.Off)) &^ 0xfff)
+			t := ldr.SymAddr(rs) + r.Add() - ((ldr.SymValue(s) + int64(r.Off())) &^ 0xfff)
 			if t&7 != 0 {
-				ld.Errorf(s, "invalid address: %x for relocation type: R_AARCH64_LD64_GOT_LO12_NC", t)
+				ldr.Errorf(s, "invalid address: %x for relocation type: R_AARCH64_LD64_GOT_LO12_NC", t)
 			}
 			var o1 uint32
 			o1 |= uint32(t&0xfff) << (10 - 3)
-			return val | int64(uint64(o1)), true
+			return val | int64(uint64(o1)), extRelocNotNeeded, isOk
 		} else {
-			ld.Errorf(s, "unsupported instruction for %v R_GOTARM64", s.P[r.Off:r.Off+4])
+			ldr.Errorf(s, "unsupported instruction for %v R_GOTARM64", sData[r.Off():r.Off()+4])
 		}
 
 	case objabi.R_ARM64_PCREL:
-		if s.P[r.Off+3]&0x9f == 0x90 {
+		sData := ldr.Data(s)
+		if sData[r.Off()+3]&0x9f == 0x90 {
 			// R_AARCH64_ADR_PREL_PG_HI21
 			// patch instruction: adrp
-			t := ld.Symaddr(r.Sym) + r.Add - ((s.Value + int64(r.Off)) &^ 0xfff)
+			t := ldr.SymAddr(rs) + r.Add() - ((ldr.SymValue(s) + int64(r.Off())) &^ 0xfff)
 			if t >= 1<<32 || t < -1<<32 {
-				ld.Errorf(s, "program too large, address relocation distance = %d", t)
+				ldr.Errorf(s, "program too large, address relocation distance = %d", t)
 			}
 			o0 := (uint32((t>>12)&3) << 29) | (uint32((t>>12>>2)&0x7ffff) << 5)
-			return val | int64(o0), true
-		} else if s.P[r.Off+3]&0x91 == 0x91 {
+			return val | int64(o0), extRelocNotNeeded, isOk
+		} else if sData[r.Off()+3]&0x91 == 0x91 {
 			// R_AARCH64_ADD_ABS_LO12_NC
 			// patch instruction: add
-			t := ld.Symaddr(r.Sym) + r.Add - ((s.Value + int64(r.Off)) &^ 0xfff)
+			t := ldr.SymAddr(rs) + r.Add() - ((ldr.SymValue(s) + int64(r.Off())) &^ 0xfff)
 			o1 := uint32(t&0xfff) << 10
-			return val | int64(o1), true
+			return val | int64(o1), extRelocNotNeeded, isOk
 		} else {
-			ld.Errorf(s, "unsupported instruction for %v R_PCRELARM64", s.P[r.Off:r.Off+4])
+			ldr.Errorf(s, "unsupported instruction for %v R_PCRELARM64", sData[r.Off():r.Off()+4])
 		}
 
 	case objabi.R_ARM64_LDST8:
-		t := ld.Symaddr(r.Sym) + r.Add - ((s.Value + int64(r.Off)) &^ 0xfff)
+		t := ldr.SymAddr(rs) + r.Add() - ((ldr.SymValue(s) + int64(r.Off())) &^ 0xfff)
 		o0 := uint32(t&0xfff) << 10
-		return val | int64(o0), true
+		return val | int64(o0), extRelocNotNeeded, true
 
 	case objabi.R_ARM64_LDST32:
-		t := ld.Symaddr(r.Sym) + r.Add - ((s.Value + int64(r.Off)) &^ 0xfff)
+		t := ldr.SymAddr(rs) + r.Add() - ((ldr.SymValue(s) + int64(r.Off())) &^ 0xfff)
 		if t&3 != 0 {
-			ld.Errorf(s, "invalid address: %x for relocation type: R_AARCH64_LDST32_ABS_LO12_NC", t)
+			ldr.Errorf(s, "invalid address: %x for relocation type: R_AARCH64_LDST32_ABS_LO12_NC", t)
 		}
 		o0 := (uint32(t&0xfff) >> 2) << 10
-		return val | int64(o0), true
+		return val | int64(o0), extRelocNotNeeded, true
 
 	case objabi.R_ARM64_LDST64:
-		t := ld.Symaddr(r.Sym) + r.Add - ((s.Value + int64(r.Off)) &^ 0xfff)
+		t := ldr.SymAddr(rs) + r.Add() - ((ldr.SymValue(s) + int64(r.Off())) &^ 0xfff)
 		if t&7 != 0 {
-			ld.Errorf(s, "invalid address: %x for relocation type: R_AARCH64_LDST64_ABS_LO12_NC", t)
+			ldr.Errorf(s, "invalid address: %x for relocation type: R_AARCH64_LDST64_ABS_LO12_NC", t)
 		}
 		o0 := (uint32(t&0xfff) >> 3) << 10
-		return val | int64(o0), true
+		return val | int64(o0), extRelocNotNeeded, true
 
 	case objabi.R_ARM64_LDST128:
-		t := ld.Symaddr(r.Sym) + r.Add - ((s.Value + int64(r.Off)) &^ 0xfff)
+		t := ldr.SymAddr(rs) + r.Add() - ((ldr.SymValue(s) + int64(r.Off())) &^ 0xfff)
 		if t&15 != 0 {
-			ld.Errorf(s, "invalid address: %x for relocation type: R_AARCH64_LDST128_ABS_LO12_NC", t)
+			ldr.Errorf(s, "invalid address: %x for relocation type: R_AARCH64_LDST128_ABS_LO12_NC", t)
 		}
 		o0 := (uint32(t&0xfff) >> 4) << 10
-		return val | int64(o0), true
+		return val | int64(o0), extRelocNotNeeded, true
 	}
 
-	return val, false
+	return val, false, false
 }
 
-func archrelocvariant(target *ld.Target, syms *ld.ArchSyms, r *sym.Reloc, s *sym.Symbol, t int64) int64 {
+func archrelocvariant(*ld.Target, *loader.Loader, loader.Reloc2, sym.RelocVariant, loader.Sym, int64) int64 {
 	log.Fatalf("unexpected relocation variant")
 	return -1
 }
@@ -757,17 +722,17 @@
 	}
 }
 
-func addpltsym2(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym) {
+func addpltsym(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym) {
 	if ldr.SymPlt(s) >= 0 {
 		return
 	}
 
-	ld.Adddynsym2(ldr, target, syms, s)
+	ld.Adddynsym(ldr, target, syms, s)
 
 	if target.IsElf() {
-		plt := ldr.MakeSymbolUpdater(syms.PLT2)
-		gotplt := ldr.MakeSymbolUpdater(syms.GOTPLT2)
-		rela := ldr.MakeSymbolUpdater(syms.RelaPLT2)
+		plt := ldr.MakeSymbolUpdater(syms.PLT)
+		gotplt := ldr.MakeSymbolUpdater(syms.GOTPLT)
+		rela := ldr.MakeSymbolUpdater(syms.RelaPLT)
 		if plt.Size() == 0 {
 			panic("plt is not set up")
 		}
@@ -809,140 +774,3 @@
 		ldr.Errorf(s, "addpltsym: unsupported binary format")
 	}
 }
-
-func addgotsym2(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym) {
-	if ldr.SymGot(s) >= 0 {
-		return
-	}
-
-	ld.Adddynsym2(ldr, target, syms, s)
-	got := ldr.MakeSymbolUpdater(syms.GOT2)
-	ldr.SetGot(s, int32(got.Size()))
-	got.AddUint64(target.Arch, 0)
-
-	if target.IsElf() {
-		rela := ldr.MakeSymbolUpdater(syms.Rela2)
-		rela.AddAddrPlus(target.Arch, got.Sym(), int64(ldr.SymGot(s)))
-		rela.AddUint64(target.Arch, ld.ELF64_R_INFO(uint32(ldr.SymDynid(s)), uint32(elf.R_AARCH64_GLOB_DAT)))
-		rela.AddUint64(target.Arch, 0)
-	} else {
-		ldr.Errorf(s, "addgotsym: unsupported binary format")
-	}
-}
-
-func asmb(ctxt *ld.Link, _ *loader.Loader) {
-	if ctxt.IsELF {
-		ld.Asmbelfsetup()
-	}
-
-	var wg sync.WaitGroup
-	sect := ld.Segtext.Sections[0]
-	offset := sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff
-	ld.WriteParallel(&wg, ld.Codeblk, ctxt, offset, sect.Vaddr, sect.Length)
-
-	for _, sect := range ld.Segtext.Sections[1:] {
-		offset := sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff
-		ld.WriteParallel(&wg, ld.Datblk, ctxt, offset, sect.Vaddr, sect.Length)
-	}
-
-	if ld.Segrodata.Filelen > 0 {
-		ld.WriteParallel(&wg, ld.Datblk, ctxt, ld.Segrodata.Fileoff, ld.Segrodata.Vaddr, ld.Segrodata.Filelen)
-	}
-
-	if ld.Segrelrodata.Filelen > 0 {
-		ld.WriteParallel(&wg, ld.Datblk, ctxt, ld.Segrelrodata.Fileoff, ld.Segrelrodata.Vaddr, ld.Segrelrodata.Filelen)
-	}
-
-	ld.WriteParallel(&wg, ld.Datblk, ctxt, ld.Segdata.Fileoff, ld.Segdata.Vaddr, ld.Segdata.Filelen)
-
-	ld.WriteParallel(&wg, ld.Dwarfblk, ctxt, ld.Segdwarf.Fileoff, ld.Segdwarf.Vaddr, ld.Segdwarf.Filelen)
-	wg.Wait()
-}
-
-func asmb2(ctxt *ld.Link) {
-	machlink := uint32(0)
-	if ctxt.HeadType == objabi.Hdarwin {
-		machlink = uint32(ld.Domacholink(ctxt))
-	}
-
-	/* output symbol table */
-	ld.Symsize = 0
-
-	ld.Lcsize = 0
-	symo := uint32(0)
-	if !*ld.FlagS {
-		// TODO: rationalize
-		switch ctxt.HeadType {
-		default:
-			if ctxt.IsELF {
-				symo = uint32(ld.Segdwarf.Fileoff + ld.Segdwarf.Filelen)
-				symo = uint32(ld.Rnd(int64(symo), int64(*ld.FlagRound)))
-			}
-
-		case objabi.Hplan9:
-			symo = uint32(ld.Segdata.Fileoff + ld.Segdata.Filelen)
-
-		case objabi.Hdarwin:
-			symo = uint32(ld.Segdwarf.Fileoff + uint64(ld.Rnd(int64(ld.Segdwarf.Filelen), int64(*ld.FlagRound))) + uint64(machlink))
-		}
-
-		ctxt.Out.SeekSet(int64(symo))
-		switch ctxt.HeadType {
-		default:
-			if ctxt.IsELF {
-				ld.Asmelfsym(ctxt)
-				ctxt.Out.Write(ld.Elfstrdat)
-
-				if ctxt.LinkMode == ld.LinkExternal {
-					ld.Elfemitreloc(ctxt)
-				}
-			}
-
-		case objabi.Hplan9:
-			ld.Asmplan9sym(ctxt)
-
-			sym := ctxt.Syms.Lookup("pclntab", 0)
-			if sym != nil {
-				ld.Lcsize = int32(len(sym.P))
-				ctxt.Out.Write(sym.P)
-			}
-
-		case objabi.Hdarwin:
-			if ctxt.LinkMode == ld.LinkExternal {
-				ld.Machoemitreloc(ctxt)
-			}
-		}
-	}
-
-	ctxt.Out.SeekSet(0)
-	switch ctxt.HeadType {
-	default:
-	case objabi.Hplan9: /* plan 9 */
-		ctxt.Out.Write32(0x647)                      /* magic */
-		ctxt.Out.Write32(uint32(ld.Segtext.Filelen)) /* sizes */
-		ctxt.Out.Write32(uint32(ld.Segdata.Filelen))
-		ctxt.Out.Write32(uint32(ld.Segdata.Length - ld.Segdata.Filelen))
-		ctxt.Out.Write32(uint32(ld.Symsize))          /* nsyms */
-		ctxt.Out.Write32(uint32(ld.Entryvalue(ctxt))) /* va of entry */
-		ctxt.Out.Write32(0)
-		ctxt.Out.Write32(uint32(ld.Lcsize))
-
-	case objabi.Hlinux,
-		objabi.Hfreebsd,
-		objabi.Hnetbsd,
-		objabi.Hopenbsd:
-		ld.Asmbelf(ctxt, int64(symo))
-
-	case objabi.Hdarwin:
-		ld.Asmbmacho(ctxt)
-	}
-
-	if *ld.FlagC {
-		fmt.Printf("textsize=%d\n", ld.Segtext.Filelen)
-		fmt.Printf("datsize=%d\n", ld.Segdata.Filelen)
-		fmt.Printf("bsssize=%d\n", ld.Segdata.Length-ld.Segdata.Filelen)
-		fmt.Printf("symsize=%d\n", ld.Symsize)
-		fmt.Printf("lcsize=%d\n", ld.Lcsize)
-		fmt.Printf("total=%d\n", ld.Segtext.Filelen+ld.Segdata.Length+uint64(ld.Symsize)+uint64(ld.Lcsize))
-	}
-}
diff --git a/src/cmd/link/internal/arm64/obj.go b/src/cmd/link/internal/arm64/obj.go
index 20426c5..8eeba0d 100644
--- a/src/cmd/link/internal/arm64/obj.go
+++ b/src/cmd/link/internal/arm64/obj.go
@@ -46,15 +46,13 @@
 		Dwarfregsp: dwarfRegSP,
 		Dwarfreglr: dwarfRegLR,
 
-		Adddynrel2:       adddynrel2,
+		Adddynrel:        adddynrel,
 		Archinit:         archinit,
 		Archreloc:        archreloc,
 		Archrelocvariant: archrelocvariant,
-		Asmb:             asmb,
-		Asmb2:            asmb2,
 		Elfreloc1:        elfreloc1,
 		Elfsetupplt:      elfsetupplt,
-		Gentext2:         gentext2,
+		Gentext:          gentext,
 		Machoreloc1:      machoreloc1,
 
 		Androiddynld: "/system/bin/linker64",
diff --git a/src/cmd/link/internal/ld/asmb.go b/src/cmd/link/internal/ld/asmb.go
new file mode 100644
index 0000000..a9987ba
--- /dev/null
+++ b/src/cmd/link/internal/ld/asmb.go
@@ -0,0 +1,161 @@
+// 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/objabi"
+	"cmd/link/internal/loader"
+	"fmt"
+	"sync"
+)
+
+// Assembling the binary is broken into two steps:
+//  - writing out the code/data/dwarf Segments
+//  - writing out the architecture specific pieces.
+// This function handles the first part.
+func asmb(ctxt *Link, ldr *loader.Loader) {
+	// TODO(jfaller): delete me.
+	if thearch.Asmb != nil {
+		thearch.Asmb(ctxt, ldr)
+		return
+	}
+
+	if ctxt.IsELF {
+		Asmbelfsetup()
+	}
+
+	var wg sync.WaitGroup
+	sect := Segtext.Sections[0]
+	offset := sect.Vaddr - Segtext.Vaddr + Segtext.Fileoff
+	f := func(ctxt *Link, out *OutBuf, start, length int64) {
+		pad := thearch.CodePad
+		if pad == nil {
+			pad = zeros[:]
+		}
+		CodeblkPad(ctxt, out, start, length, pad)
+	}
+
+	if !thearch.WriteTextBlocks {
+		writeParallel(&wg, f, ctxt, offset, sect.Vaddr, sect.Length)
+		for _, sect := range Segtext.Sections[1:] {
+			offset := sect.Vaddr - Segtext.Vaddr + Segtext.Fileoff
+			writeParallel(&wg, Datblk, ctxt, offset, sect.Vaddr, sect.Length)
+		}
+	} else {
+		// TODO why can't we handle all sections this way?
+		for _, sect := range Segtext.Sections {
+			offset := sect.Vaddr - Segtext.Vaddr + Segtext.Fileoff
+			// Handle additional text sections with Codeblk
+			if sect.Name == ".text" {
+				writeParallel(&wg, f, ctxt, offset, sect.Vaddr, sect.Length)
+			} else {
+				writeParallel(&wg, Datblk, ctxt, offset, sect.Vaddr, sect.Length)
+			}
+		}
+	}
+
+	if Segrodata.Filelen > 0 {
+		writeParallel(&wg, Datblk, ctxt, Segrodata.Fileoff, Segrodata.Vaddr, Segrodata.Filelen)
+	}
+
+	if Segrelrodata.Filelen > 0 {
+		writeParallel(&wg, Datblk, ctxt, Segrelrodata.Fileoff, Segrelrodata.Vaddr, Segrelrodata.Filelen)
+	}
+
+	writeParallel(&wg, Datblk, ctxt, Segdata.Fileoff, Segdata.Vaddr, Segdata.Filelen)
+
+	writeParallel(&wg, dwarfblk, ctxt, Segdwarf.Fileoff, Segdwarf.Vaddr, Segdwarf.Filelen)
+
+	wg.Wait()
+}
+
+// Assembling the binary is broken into two steps:
+//  - writing out the code/data/dwarf Segments
+//  - writing out the architecture specific pieces.
+// This function handles the second part.
+func asmb2(ctxt *Link) {
+	if thearch.Asmb2 != nil {
+		thearch.Asmb2(ctxt, ctxt.loader)
+		return
+	}
+
+	symSize = 0
+	spSize = 0
+	lcSize = 0
+
+	switch ctxt.HeadType {
+	default:
+		panic("unknown platform")
+
+	// Macho
+	case objabi.Hdarwin:
+		asmbMacho(ctxt)
+
+	// Plan9
+	case objabi.Hplan9:
+		asmbPlan9(ctxt)
+
+	// PE
+	case objabi.Hwindows:
+		asmbPe(ctxt)
+
+	// Xcoff
+	case objabi.Haix:
+		asmbXcoff(ctxt)
+
+	// Elf
+	case objabi.Hdragonfly,
+		objabi.Hfreebsd,
+		objabi.Hlinux,
+		objabi.Hnetbsd,
+		objabi.Hopenbsd,
+		objabi.Hsolaris:
+		asmbElf(ctxt)
+	}
+
+	if *FlagC {
+		fmt.Printf("textsize=%d\n", Segtext.Filelen)
+		fmt.Printf("datsize=%d\n", Segdata.Filelen)
+		fmt.Printf("bsssize=%d\n", Segdata.Length-Segdata.Filelen)
+		fmt.Printf("symsize=%d\n", symSize)
+		fmt.Printf("lcsize=%d\n", lcSize)
+		fmt.Printf("total=%d\n", Segtext.Filelen+Segdata.Length+uint64(symSize)+uint64(lcSize))
+	}
+}
+
+// writePlan9Header writes out the plan9 header at the present position in the OutBuf.
+func writePlan9Header(buf *OutBuf, magic uint32, entry int64, is64Bit bool) {
+	if is64Bit {
+		magic |= 0x00008000
+	}
+	buf.Write32b(magic)
+	buf.Write32b(uint32(Segtext.Filelen))
+	buf.Write32b(uint32(Segdata.Filelen))
+	buf.Write32b(uint32(Segdata.Length - Segdata.Filelen))
+	buf.Write32b(uint32(symSize))
+	if is64Bit {
+		buf.Write32b(uint32(entry &^ 0x80000000))
+	} else {
+		buf.Write32b(uint32(entry))
+	}
+	buf.Write32b(uint32(spSize))
+	buf.Write32b(uint32(lcSize))
+	// amd64 includes the entry at the beginning of the symbol table.
+	if is64Bit {
+		buf.Write64b(uint64(entry))
+	}
+}
+
+// asmbPlan9 assembles a plan 9 binary.
+func asmbPlan9(ctxt *Link) {
+	if !*FlagS {
+		*FlagS = true
+		symo := int64(Segdata.Fileoff + Segdata.Filelen)
+		ctxt.Out.SeekSet(symo)
+		asmbPlan9Sym(ctxt)
+	}
+	ctxt.Out.SeekSet(0)
+	writePlan9Header(ctxt.Out, thearch.Plan9Magic, Entryvalue(ctxt), thearch.Plan9_64Bit)
+}
diff --git a/src/cmd/link/internal/ld/data.go b/src/cmd/link/internal/ld/data.go
index d3f308c..8fec08b 100644
--- a/src/cmd/link/internal/ld/data.go
+++ b/src/cmd/link/internal/ld/data.go
@@ -120,16 +120,15 @@
 
 }
 
-// foldSubSymbolOffset computes the offset of symbol s to its top-level outer
+// FoldSubSymbolOffset computes the offset of symbol s to its top-level outer
 // symbol. Returns the top-level symbol and the offset.
 // This is used in generating external relocations.
-func foldSubSymbolOffset(ldr *loader.Loader, s loader.Sym) (loader.Sym, int64) {
+func FoldSubSymbolOffset(ldr *loader.Loader, s loader.Sym) (loader.Sym, int64) {
 	outer := ldr.OuterSym(s)
 	off := int64(0)
-	for outer != 0 {
+	if outer != 0 {
 		off += ldr.SymValue(s) - ldr.SymValue(outer)
 		s = outer
-		outer = ldr.OuterSym(s)
 	}
 	return s, off
 }
@@ -179,6 +178,9 @@
 			st.err.Errorf(s, "invalid relocation %s: %d+%d not in [%d,%d)", rname, off, siz, 0, len(P))
 			continue
 		}
+		if siz == 0 { // informational relocation - no work to do
+			continue
+		}
 
 		var rst sym.SymKind
 		if rs != 0 {
@@ -206,9 +208,6 @@
 		if rt >= objabi.ElfRelocOffset {
 			continue
 		}
-		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
@@ -227,18 +226,21 @@
 			rr.Idx = ri
 		}
 
+		var rv sym.RelocVariant
+		if target.IsPPC64() || target.IsS390X() {
+			rv = ldr.RelocVariant(s, ri)
+		}
+
 		// 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 rt {
+			case objabi.R_PCRELDBL:
+				rt = objabi.R_PCREL
+				rv = sym.RV_390_DBL
+			case objabi.R_CALL:
+				rv = sym.RV_390_DBL
+			}
+		}
 
 		var o int64
 		switch rt {
@@ -257,14 +259,14 @@
 			}
 			var rp *loader.ExtReloc
 			if target.IsExternal() {
-				// Don't pass &rr directly to Archreloc2, which will escape rr
+				// Don't pass &rr directly to Archreloc, which will escape rr
 				// even if this case is not taken. Instead, as Archreloc2 will
 				// likely return true, we speculatively add rr to extRelocs
-				// and use that space to pass to Archreloc2.
+				// and use that space to pass to Archreloc.
 				extRelocs = append(extRelocs, rr)
 				rp = &extRelocs[len(extRelocs)-1]
 			}
-			out, needExtReloc1, ok := thearch.Archreloc2(target, ldr, syms, r, rp, s, o)
+			out, needExtReloc1, ok := thearch.Archreloc(target, ldr, syms, r, rp, s, o)
 			if target.IsExternal() && !needExtReloc1 {
 				// Speculation failed. Undo the append.
 				extRelocs = extRelocs[:len(extRelocs)-1]
@@ -280,7 +282,7 @@
 				needExtReloc = true
 				rr.Xsym = rs
 				if rr.Xsym == 0 {
-					rr.Xsym = syms.Tlsg2
+					rr.Xsym = syms.Tlsg
 				}
 				rr.Xadd = r.Add()
 				o = 0
@@ -311,7 +313,7 @@
 				needExtReloc = true
 				rr.Xsym = rs
 				if rr.Xsym == 0 {
-					rr.Xsym = syms.Tlsg2
+					rr.Xsym = syms.Tlsg
 				}
 				rr.Xadd = r.Add()
 				o = 0
@@ -332,12 +334,12 @@
 				log.Fatalf("cannot handle R_TLS_IE (sym %s) when linking internally", ldr.SymName(s))
 			}
 		case objabi.R_ADDR:
-			if target.IsExternal() && rst != sym.SCONST {
+			if target.IsExternal() {
 				needExtReloc = true
 
 				// set up addend for eventual relocation via outer symbol.
 				rs := rs
-				rs, off := foldSubSymbolOffset(ldr, rs)
+				rs, off := FoldSubSymbolOffset(ldr, rs)
 				rr.Xadd = r.Add() + off
 				rst := ldr.SymType(rs)
 				if rst != sym.SHOSTOBJ && rst != sym.SDYNIMPORT && rst != sym.SUNDEFEXT && ldr.SymSect(rs) == nil {
@@ -357,7 +359,7 @@
 				} else if target.IsWindows() {
 					// nothing to do
 				} else if target.IsAIX() {
-					o = ldr.SymValue(rs) + r.Add()
+					o = ldr.SymValue(rs) + rr.Xadd
 				} else {
 					st.err.Errorf(s, "unhandled pcrel relocation to %s on %v", ldr.SymName(rs), target.HeadType)
 				}
@@ -376,8 +378,7 @@
 				// symbol which isn't in .data. However, as .text has the
 				// same address once loaded, this is possible.
 				if ldr.SymSect(s).Seg == &Segdata {
-					panic("not implemented")
-					//Xcoffadddynrel(target, ldr, err, s, &r) // XXX
+					Xcoffadddynrel(target, ldr, syms, s, r, ri)
 				}
 			}
 
@@ -409,7 +410,7 @@
 					needExtReloc = false
 				}
 
-				rr.Xsym = loader.Sym(ldr.SymSect(rs).Sym2)
+				rr.Xsym = loader.Sym(ldr.SymSect(rs).Sym)
 				rr.Xadd = r.Add() + ldr.SymValue(rs) - int64(ldr.SymSect(rs).Vaddr)
 
 				o = rr.Xadd
@@ -436,11 +437,11 @@
 		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 = ldr.SymValue(rs) + r.Add() - ldr.SymValue(loader.Sym(ldr.SymUnit(rs).Textp2[0]))
+			o = ldr.SymValue(rs) + r.Add() - ldr.SymValue(loader.Sym(ldr.SymUnit(rs).Textp[0]))
 
 		// 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() && rs != 0 && rst != sym.SCONST {
+			if target.IsDynlinkingGo() && target.IsDarwin() && rs != 0 {
 				needExtReloc = true
 				rr.Xadd = r.Add()
 				rr.Xadd -= int64(siz) // relative to address after the relocated chunk
@@ -463,12 +464,12 @@
 				o = 0
 				break
 			}
-			if target.IsExternal() && rs != 0 && rst != sym.SCONST && (ldr.SymSect(rs) != ldr.SymSect(s) || rt == objabi.R_GOTPCREL) {
+			if target.IsExternal() && rs != 0 && (ldr.SymSect(rs) != ldr.SymSect(s) || rt == objabi.R_GOTPCREL) {
 				needExtReloc = true
 
 				// set up addend for eventual relocation via outer symbol.
 				rs := rs
-				rs, off := foldSubSymbolOffset(ldr, rs)
+				rs, off := FoldSubSymbolOffset(ldr, rs)
 				rr.Xadd = r.Add() + off
 				rr.Xadd -= int64(siz) // relative to address after the relocated chunk
 				rst := ldr.SymType(rs)
@@ -528,10 +529,7 @@
 			needExtReloc = true
 			rr.Xsym = rs
 			rr.Xadd = r.Add()
-
-			// This isn't a real relocation so it must not update
-			// its offset value.
-			continue
+			goto addExtReloc
 
 		case objabi.R_DWARFFILEREF:
 			// We don't renumber files in dwarf.go:writelines anymore.
@@ -541,15 +539,14 @@
 			o = r.Add()
 
 		case objabi.R_GOTOFF:
-			o = ldr.SymValue(rs) + r.Add() - ldr.SymValue(syms.GOT2)
+			o = ldr.SymValue(rs) + r.Add() - ldr.SymValue(syms.GOT)
 		}
 
-		//if target.IsPPC64() || target.IsS390X() {
-		//	r.InitExt()
-		//	if r.Variant != sym.RV_NONE {
-		//		o = thearch.Archrelocvariant(ldr, target, syms, &r, s, o)
-		//	}
-		//}
+		if target.IsPPC64() || target.IsS390X() {
+			if rv != sym.RV_NONE {
+				o = thearch.Archrelocvariant(target, ldr, r, rv, s, o)
+			}
+		}
 
 		switch siz {
 		default:
@@ -576,6 +573,7 @@
 			target.Arch.ByteOrder.PutUint64(P[off:], uint64(o))
 		}
 
+	addExtReloc:
 		if needExtReloc {
 			extRelocs = append(extRelocs, rr)
 		}
@@ -652,7 +650,7 @@
 	go func() {
 		if !ctxt.IsWasm() { // On Wasm, text relocations are applied in Asmb2.
 			st := ctxt.makeRelocSymState()
-			for _, s := range ctxt.Textp2 {
+			for _, s := range ctxt.Textp {
 				st.relocsym(s, ldr.OutData(s))
 			}
 		}
@@ -660,14 +658,14 @@
 	}()
 	go func() {
 		st := ctxt.makeRelocSymState()
-		for _, s := range ctxt.datap2 {
+		for _, s := range ctxt.datap {
 			st.relocsym(s, ldr.OutData(s))
 		}
 		wg.Done()
 	}()
 	go func() {
 		st := ctxt.makeRelocSymState()
-		for _, si := range dwarfp2 {
+		for _, si := range dwarfp {
 			for _, s := range si.syms {
 				st.relocsym(s, ldr.OutData(s))
 			}
@@ -746,14 +744,14 @@
 	relu := ctxt.loader.MakeSymbolUpdater(rel)
 	relu.SetType(sym.STEXT)
 
-	for _, s := range ctxt.Textp2 {
+	for _, s := range ctxt.Textp {
 		windynrelocsym(ctxt, relu, s)
 	}
 
-	ctxt.Textp2 = append(ctxt.Textp2, rel)
+	ctxt.Textp = append(ctxt.Textp, rel)
 }
 
-func dynrelocsym2(ctxt *Link, s loader.Sym) {
+func dynrelocsym(ctxt *Link, s loader.Sym) {
 	target := &ctxt.Target
 	ldr := ctxt.loader
 	syms := &ctxt.ArchSyms
@@ -764,7 +762,7 @@
 			// It's expected that some relocations will be done
 			// later by relocsym (R_TLS_LE, R_ADDROFF), so
 			// don't worry if Adddynrel returns false.
-			thearch.Adddynrel2(target, ldr, syms, s, r, ri)
+			thearch.Adddynrel(target, ldr, syms, s, r, ri)
 			continue
 		}
 
@@ -773,14 +771,14 @@
 			if rSym != 0 && !ldr.AttrReachable(rSym) {
 				ctxt.Errorf(s, "dynamic relocation to unreachable symbol %s", ldr.SymName(rSym))
 			}
-			if !thearch.Adddynrel2(target, ldr, syms, s, r, ri) {
+			if !thearch.Adddynrel(target, ldr, syms, s, r, ri) {
 				ctxt.Errorf(s, "unsupported dynamic relocation for symbol %s (type=%d (%s) stype=%d (%s))", ldr.SymName(rSym), r.Type(), sym.RelocName(ctxt.Arch, r.Type()), ldr.SymType(rSym), ldr.SymType(rSym))
 			}
 		}
 	}
 }
 
-func (state *dodataState) dynreloc2(ctxt *Link) {
+func (state *dodataState) dynreloc(ctxt *Link) {
 	if ctxt.HeadType == objabi.Hwindows {
 		return
 	}
@@ -790,25 +788,21 @@
 		return
 	}
 
-	for _, s := range ctxt.Textp2 {
-		dynrelocsym2(ctxt, s)
+	for _, s := range ctxt.Textp {
+		dynrelocsym(ctxt, s)
 	}
-	for _, syms := range state.data2 {
+	for _, syms := range state.data {
 		for _, s := range syms {
-			dynrelocsym2(ctxt, s)
+			dynrelocsym(ctxt, s)
 		}
 	}
 	if ctxt.IsELF {
-		elfdynhash2(ctxt)
+		elfdynhash(ctxt)
 	}
 }
 
-func Codeblk(ctxt *Link, out *OutBuf, addr int64, size int64) {
-	CodeblkPad(ctxt, out, addr, size, zeros[:])
-}
-
 func CodeblkPad(ctxt *Link, out *OutBuf, addr int64, size int64, pad []byte) {
-	writeBlocks(out, ctxt.outSem, ctxt.loader, ctxt.Textp2, addr, size, pad)
+	writeBlocks(out, ctxt.outSem, ctxt.loader, ctxt.Textp, addr, size, pad)
 }
 
 const blockSize = 1 << 20 // 1MB chunks written at a time.
@@ -953,8 +947,8 @@
 
 type writeFn func(*Link, *OutBuf, int64, int64)
 
-// WriteParallel handles scheduling parallel execution of data write functions.
-func WriteParallel(wg *sync.WaitGroup, fn writeFn, ctxt *Link, seek, vaddr, length uint64) {
+// writeParallel handles scheduling parallel execution of data write functions.
+func writeParallel(wg *sync.WaitGroup, fn writeFn, ctxt *Link, seek, vaddr, length uint64) {
 	if out, err := ctxt.Out.View(seek); err != nil {
 		ctxt.Out.SeekSet(int64(seek))
 		fn(ctxt, ctxt.Out, int64(vaddr), int64(length))
@@ -980,10 +974,10 @@
 }
 
 func writeDatblkToOutBuf(ctxt *Link, out *OutBuf, addr int64, size int64) {
-	writeBlocks(out, ctxt.outSem, ctxt.loader, ctxt.datap2, addr, size, zeros[:])
+	writeBlocks(out, ctxt.outSem, ctxt.loader, ctxt.datap, addr, size, zeros[:])
 }
 
-func Dwarfblk(ctxt *Link, out *OutBuf, addr int64, size int64) {
+func dwarfblk(ctxt *Link, out *OutBuf, addr int64, size int64) {
 	// Concatenate the section symbol lists into a single list to pass
 	// to writeBlocks.
 	//
@@ -991,12 +985,12 @@
 	// section, but this would run the risk of undoing any file offset
 	// adjustments made during layout.
 	n := 0
-	for i := range dwarfp2 {
-		n += len(dwarfp2[i].syms)
+	for i := range dwarfp {
+		n += len(dwarfp[i].syms)
 	}
 	syms := make([]loader.Sym, 0, n)
-	for i := range dwarfp2 {
-		syms = append(syms, dwarfp2[i].syms...)
+	for i := range dwarfp {
+		syms = append(syms, dwarfp[i].syms...)
 	}
 	writeBlocks(out, ctxt.outSem, ctxt.loader, syms, addr, size, zeros[:])
 }
@@ -1094,9 +1088,8 @@
 }
 
 // symalign returns the required alignment for the given symbol s.
-func (state *dodataState) symalign2(s loader.Sym) int32 {
+func symalign(ldr *loader.Loader, s loader.Sym) int32 {
 	min := int32(thearch.Minalign)
-	ldr := state.ctxt.loader
 	align := ldr.SymAlign(s)
 	if align >= min {
 		return align
@@ -1119,19 +1112,19 @@
 	return align
 }
 
-func aligndatsize2(state *dodataState, datsize int64, s loader.Sym) int64 {
-	return Rnd(datsize, int64(state.symalign2(s)))
+func aligndatsize(state *dodataState, datsize int64, s loader.Sym) int64 {
+	return Rnd(datsize, int64(symalign(state.ctxt.loader, s)))
 }
 
 const debugGCProg = false
 
-type GCProg2 struct {
+type GCProg struct {
 	ctxt *Link
 	sym  *loader.SymbolBuilder
 	w    gcprog.Writer
 }
 
-func (p *GCProg2) Init(ctxt *Link, name string) {
+func (p *GCProg) Init(ctxt *Link, name string) {
 	p.ctxt = ctxt
 	symIdx := ctxt.loader.LookupOrCreateSym(name, 0)
 	p.sym = ctxt.loader.MakeSymbolUpdater(symIdx)
@@ -1142,13 +1135,13 @@
 	}
 }
 
-func (p *GCProg2) writeByte() func(x byte) {
+func (p *GCProg) writeByte() func(x byte) {
 	return func(x byte) {
 		p.sym.AddUint8(x)
 	}
 }
 
-func (p *GCProg2) End(size int64) {
+func (p *GCProg) End(size int64) {
 	p.w.ZeroUntil(size / int64(p.ctxt.Arch.PtrSize))
 	p.w.End()
 	if debugGCProg {
@@ -1156,7 +1149,7 @@
 	}
 }
 
-func (p *GCProg2) AddSym(s loader.Sym) {
+func (p *GCProg) AddSym(s loader.Sym) {
 	ldr := p.ctxt.loader
 	typ := ldr.SymGoType(s)
 
@@ -1211,7 +1204,7 @@
 }
 
 // fixZeroSizedSymbols gives a few special symbols with zero size some space.
-func fixZeroSizedSymbols2(ctxt *Link) {
+func fixZeroSizedSymbols(ctxt *Link) {
 	// The values in moduledata are filled out by relocations
 	// pointing to the addresses of these special symbols.
 	// Typically these symbols have no size and are not laid
@@ -1280,7 +1273,7 @@
 }
 
 // makeRelroForSharedLib creates a section of readonly data if necessary.
-func (state *dodataState) makeRelroForSharedLib2(target *Link) {
+func (state *dodataState) makeRelroForSharedLib(target *Link) {
 	if !target.UseRelro() {
 		return
 	}
@@ -1293,9 +1286,9 @@
 		symnrelro := sym.RelROMap[symnro]
 
 		ro := []loader.Sym{}
-		relro := state.data2[symnrelro]
+		relro := state.data[symnrelro]
 
-		for _, s := range state.data2[symnro] {
+		for _, s := range state.data[symnro] {
 			relocs := ldr.Relocs(s)
 			isRelro := relocs.Count() > 0
 			switch state.symType(s) {
@@ -1337,8 +1330,8 @@
 			}
 		}
 
-		state.data2[symnro] = ro
-		state.data2[symnrelro] = relro
+		state.data[symnro] = ro
+		state.data[symnrelro] = relro
 	}
 }
 
@@ -1349,9 +1342,7 @@
 	// Link context
 	ctxt *Link
 	// Data symbols bucketed by type.
-	data [sym.SXREF][]*sym.Symbol
-	// Data symbols bucketed by type.
-	data2 [sym.SXREF][]loader.Sym
+	data [sym.SXREF][]loader.Sym
 	// Max alignment for each flavor of data symbol.
 	dataMaxAlign [sym.SXREF]int32
 	// Overridden sym type
@@ -1394,10 +1385,10 @@
 	}
 }
 
-func (ctxt *Link) dodata2(symGroupType []sym.SymKind) {
+func (ctxt *Link) dodata(symGroupType []sym.SymKind) {
 
 	// Give zeros sized symbols space if necessary.
-	fixZeroSizedSymbols2(ctxt)
+	fixZeroSizedSymbols(ctxt)
 
 	// Collect data symbols by type into data.
 	state := dodataState{ctxt: ctxt, symGroupType: symGroupType}
@@ -1413,7 +1404,7 @@
 		if st <= sym.STEXT || st >= sym.SXREF {
 			continue
 		}
-		state.data2[st] = append(state.data2[st], s)
+		state.data[st] = append(state.data[st], s)
 
 		// Similarly with checking the onlist attr.
 		if ldr.AttrOnList(s) {
@@ -1431,10 +1422,10 @@
 	if ctxt.HeadType == objabi.Hdarwin {
 		machosymorder(ctxt)
 	}
-	state.dynreloc2(ctxt)
+	state.dynreloc(ctxt)
 
 	// Move any RO data with relocations to a separate section.
-	state.makeRelroForSharedLib2(ctxt)
+	state.makeRelroForSharedLib(ctxt)
 
 	// Set alignment for the symbol with the largest known index,
 	// so as to trigger allocation of the loader's internal
@@ -1445,11 +1436,11 @@
 
 	// Sort symbols.
 	var wg sync.WaitGroup
-	for symn := range state.data2 {
+	for symn := range state.data {
 		symn := sym.SymKind(symn)
 		wg.Add(1)
 		go func() {
-			state.data2[symn], state.dataMaxAlign[symn] = state.dodataSect2(ctxt, symn, state.data2[symn])
+			state.data[symn], state.dataMaxAlign[symn] = state.dodataSect(ctxt, symn, state.data[symn])
 			wg.Done()
 		}()
 	}
@@ -1458,7 +1449,7 @@
 	if ctxt.IsELF {
 		// Make .rela and .rela.plt contiguous, the ELF ABI requires this
 		// and Solaris actually cares.
-		syms := state.data2[sym.SELFROSECT]
+		syms := state.data[sym.SELFROSECT]
 		reli, plti := -1, -1
 		for i, s := range syms {
 			switch ldr.SymName(s) {
@@ -1487,7 +1478,7 @@
 			ldr.SetSymAlign(rel, int32(ctxt.Arch.RegSize))
 			ldr.SetSymAlign(plt, int32(ctxt.Arch.RegSize))
 		}
-		state.data2[sym.SELFROSECT] = syms
+		state.data[sym.SELFROSECT] = syms
 	}
 
 	if ctxt.HeadType == objabi.Haix && ctxt.LinkMode == LinkExternal {
@@ -1499,11 +1490,11 @@
 
 	// Create *sym.Section objects and assign symbols to sections for
 	// data/rodata (and related) symbols.
-	state.allocateDataSections2(ctxt)
+	state.allocateDataSections(ctxt)
 
 	// Create *sym.Section objects and assign symbols to sections for
 	// DWARF symbols.
-	state.allocateDwarfSections2(ctxt)
+	state.allocateDwarfSections(ctxt)
 
 	/* number the sections */
 	n := int16(1)
@@ -1534,11 +1525,11 @@
 // single symbol will be placed. Here "seg" is the segment into which
 // the section will go, "s" is the symbol to be placed into the new
 // section, and "rwx" contains permissions for the section.
-func (state *dodataState) allocateDataSectionForSym2(seg *sym.Segment, s loader.Sym, rwx int) *sym.Section {
+func (state *dodataState) allocateDataSectionForSym(seg *sym.Segment, s loader.Sym, rwx int) *sym.Section {
 	ldr := state.ctxt.loader
 	sname := ldr.SymName(s)
 	sect := addsection(ldr, state.ctxt.Arch, seg, sname, rwx)
-	sect.Align = state.symalign2(s)
+	sect.Align = symalign(ldr, s)
 	state.datsize = Rnd(state.datsize, int64(sect.Align))
 	sect.Vaddr = uint64(state.datsize)
 	return sect
@@ -1574,7 +1565,7 @@
 // "forceType" (if non-zero) contains a new sym type to apply to each
 // sym during the assignment, and "aligner" is a hook to call to
 // handle alignment during the assignment process.
-func (state *dodataState) assignDsymsToSection2(sect *sym.Section, syms []loader.Sym, forceType sym.SymKind, aligner func(state *dodataState, datsize int64, s loader.Sym) int64) {
+func (state *dodataState) assignDsymsToSection(sect *sym.Section, syms []loader.Sym, forceType sym.SymKind, aligner func(state *dodataState, datsize int64, s loader.Sym) int64) {
 	ldr := state.ctxt.loader
 	for _, s := range syms {
 		state.datsize = aligner(state, state.datsize, s)
@@ -1588,8 +1579,8 @@
 	sect.Length = uint64(state.datsize) - sect.Vaddr
 }
 
-func (state *dodataState) assignToSection2(sect *sym.Section, symn sym.SymKind, forceType sym.SymKind) {
-	state.assignDsymsToSection2(sect, state.data2[symn], forceType, aligndatsize2)
+func (state *dodataState) assignToSection(sect *sym.Section, symn sym.SymKind, forceType sym.SymKind) {
+	state.assignDsymsToSection(sect, state.data[symn], forceType, aligndatsize)
 	state.checkdatsize(symn)
 }
 
@@ -1599,10 +1590,10 @@
 // symbol name. "Seg" is the segment into which to place the new
 // section, "forceType" is the new sym.SymKind to assign to the symbol
 // within the section, and "rwx" holds section permissions.
-func (state *dodataState) allocateSingleSymSections2(seg *sym.Segment, symn sym.SymKind, forceType sym.SymKind, rwx int) {
+func (state *dodataState) allocateSingleSymSections(seg *sym.Segment, symn sym.SymKind, forceType sym.SymKind, rwx int) {
 	ldr := state.ctxt.loader
-	for _, s := range state.data2[symn] {
-		sect := state.allocateDataSectionForSym2(seg, s, rwx)
+	for _, s := range state.data[symn] {
+		sect := state.allocateDataSectionForSym(seg, s, rwx)
 		ldr.SetSymSect(s, sect)
 		state.setSymType(s, forceType)
 		ldr.SetSymValue(s, int64(uint64(state.datsize)-sect.Vaddr))
@@ -1619,16 +1610,16 @@
 // name to give to the new section, "forceType" (if non-zero) contains
 // a new sym type to apply to each sym during the assignment, and
 // "rwx" holds section permissions.
-func (state *dodataState) allocateNamedSectionAndAssignSyms2(seg *sym.Segment, secName string, symn sym.SymKind, forceType sym.SymKind, rwx int) *sym.Section {
+func (state *dodataState) allocateNamedSectionAndAssignSyms(seg *sym.Segment, secName string, symn sym.SymKind, forceType sym.SymKind, rwx int) *sym.Section {
 
 	sect := state.allocateNamedDataSection(seg, secName, []sym.SymKind{symn}, rwx)
-	state.assignDsymsToSection2(sect, state.data2[symn], forceType, aligndatsize2)
+	state.assignDsymsToSection(sect, state.data[symn], forceType, aligndatsize)
 	return sect
 }
 
 // allocateDataSections allocates sym.Section objects for data/rodata
 // (and related) symbols, and then assigns symbols to those sections.
-func (state *dodataState) allocateDataSections2(ctxt *Link) {
+func (state *dodataState) allocateDataSections(ctxt *Link) {
 	// Allocate sections.
 	// Data is processed before segtext, because we need
 	// to see all symbols in the .data and .bss sections in order
@@ -1643,15 +1634,15 @@
 		sym.SWINDOWS,
 	}
 	for _, symn := range writable {
-		state.allocateSingleSymSections2(&Segdata, symn, sym.SDATA, 06)
+		state.allocateSingleSymSections(&Segdata, symn, sym.SDATA, 06)
 	}
 	ldr := ctxt.loader
 
 	// .got (and .toc on ppc64)
-	if len(state.data2[sym.SELFGOT]) > 0 {
-		sect := state.allocateNamedSectionAndAssignSyms2(&Segdata, ".got", sym.SELFGOT, sym.SDATA, 06)
+	if len(state.data[sym.SELFGOT]) > 0 {
+		sect := state.allocateNamedSectionAndAssignSyms(&Segdata, ".got", sym.SELFGOT, sym.SDATA, 06)
 		if ctxt.IsPPC64() {
-			for _, s := range state.data2[sym.SELFGOT] {
+			for _, s := range state.data[sym.SELFGOT] {
 				// Resolve .TOC. symbol for this object file (ppc64)
 
 				toc := ldr.Lookup(".TOC.", int(ldr.SymVersion(s)))
@@ -1665,7 +1656,7 @@
 	}
 
 	/* pointer-free data */
-	sect := state.allocateNamedSectionAndAssignSyms2(&Segdata, ".noptrdata", sym.SNOPTRDATA, sym.SDATA, 06)
+	sect := state.allocateNamedSectionAndAssignSyms(&Segdata, ".noptrdata", sym.SNOPTRDATA, sym.SDATA, 06)
 	ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.noptrdata", 0), sect)
 	ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.enoptrdata", 0), sect)
 
@@ -1678,29 +1669,29 @@
 	}
 
 	if ctxt.HeadType == objabi.Haix {
-		if len(state.data2[sym.SINITARR]) > 0 {
+		if len(state.data[sym.SINITARR]) > 0 {
 			Errorf(nil, "XCOFF format doesn't allow .init_array section")
 		}
 	}
 
-	if hasinitarr && len(state.data2[sym.SINITARR]) > 0 {
-		state.allocateNamedSectionAndAssignSyms2(&Segdata, ".init_array", sym.SINITARR, sym.Sxxx, 06)
+	if hasinitarr && len(state.data[sym.SINITARR]) > 0 {
+		state.allocateNamedSectionAndAssignSyms(&Segdata, ".init_array", sym.SINITARR, sym.Sxxx, 06)
 	}
 
 	/* data */
-	sect = state.allocateNamedSectionAndAssignSyms2(&Segdata, ".data", sym.SDATA, sym.SDATA, 06)
+	sect = state.allocateNamedSectionAndAssignSyms(&Segdata, ".data", sym.SDATA, sym.SDATA, 06)
 	ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.data", 0), sect)
 	ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.edata", 0), sect)
 	dataGcEnd := state.datsize - int64(sect.Vaddr)
 
 	// On AIX, TOC entries must be the last of .data
 	// These aren't part of gc as they won't change during the runtime.
-	state.assignToSection2(sect, sym.SXCOFFTOC, sym.SDATA)
+	state.assignToSection(sect, sym.SXCOFFTOC, sym.SDATA)
 	state.checkdatsize(sym.SDATA)
 	sect.Length = uint64(state.datsize) - sect.Vaddr
 
 	/* bss */
-	sect = state.allocateNamedSectionAndAssignSyms2(&Segdata, ".bss", sym.SBSS, sym.Sxxx, 06)
+	sect = state.allocateNamedSectionAndAssignSyms(&Segdata, ".bss", sym.SBSS, sym.Sxxx, 06)
 	ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.bss", 0), sect)
 	ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.ebss", 0), sect)
 	bssGcEnd := state.datsize - int64(sect.Vaddr)
@@ -1715,26 +1706,26 @@
 		{"runtime.gcbss", sym.SBSS, bssGcEnd},
 	}
 	for _, g := range gcsToEmit {
-		var gc GCProg2
+		var gc GCProg
 		gc.Init(ctxt, g.symName)
-		for _, s := range state.data2[g.symKind] {
+		for _, s := range state.data[g.symKind] {
 			gc.AddSym(s)
 		}
 		gc.End(g.gcEnd)
 	}
 
 	/* pointer-free bss */
-	sect = state.allocateNamedSectionAndAssignSyms2(&Segdata, ".noptrbss", sym.SNOPTRBSS, sym.Sxxx, 06)
+	sect = state.allocateNamedSectionAndAssignSyms(&Segdata, ".noptrbss", sym.SNOPTRBSS, sym.Sxxx, 06)
 	ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.noptrbss", 0), sect)
 	ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.enoptrbss", 0), sect)
 	ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.end", 0), sect)
 
 	// Coverage instrumentation counters for libfuzzer.
-	if len(state.data2[sym.SLIBFUZZER_EXTRA_COUNTER]) > 0 {
-		state.allocateNamedSectionAndAssignSyms2(&Segdata, "__libfuzzer_extra_counters", sym.SLIBFUZZER_EXTRA_COUNTER, sym.Sxxx, 06)
+	if len(state.data[sym.SLIBFUZZER_EXTRA_COUNTER]) > 0 {
+		state.allocateNamedSectionAndAssignSyms(&Segdata, "__libfuzzer_extra_counters", sym.SLIBFUZZER_EXTRA_COUNTER, sym.Sxxx, 06)
 	}
 
-	if len(state.data2[sym.STLSBSS]) > 0 {
+	if len(state.data[sym.STLSBSS]) > 0 {
 		var sect *sym.Section
 		// FIXME: not clear why it is sometimes necessary to suppress .tbss section creation.
 		if (ctxt.IsELF || ctxt.HeadType == objabi.Haix) && (ctxt.LinkMode == LinkExternal || !*FlagD) {
@@ -1745,8 +1736,8 @@
 		}
 		state.datsize = 0
 
-		for _, s := range state.data2[sym.STLSBSS] {
-			state.datsize = aligndatsize2(state, state.datsize, s)
+		for _, s := range state.data[sym.STLSBSS] {
+			state.datsize = aligndatsize(state, state.datsize, s)
 			if sect != nil {
 				ldr.SetSymSect(s, sect)
 			}
@@ -1781,11 +1772,11 @@
 	state.datsize = 0
 
 	/* read-only executable ELF, Mach-O sections */
-	if len(state.data2[sym.STEXT]) != 0 {
-		culprit := ldr.SymName(state.data2[sym.STEXT][0])
+	if len(state.data[sym.STEXT]) != 0 {
+		culprit := ldr.SymName(state.data[sym.STEXT][0])
 		Errorf(nil, "dodata found an sym.STEXT symbol: %s", culprit)
 	}
-	state.allocateSingleSymSections2(&Segtext, sym.SELFRXSECT, sym.SRODATA, 04)
+	state.allocateSingleSymSections(&Segtext, sym.SELFRXSECT, sym.SRODATA, 04)
 
 	/* read-only data */
 	sect = state.allocateNamedDataSection(segro, ".rodata", sym.ReadOnly, 04)
@@ -1797,19 +1788,19 @@
 	}
 	for _, symn := range sym.ReadOnly {
 		symnStartValue := state.datsize
-		state.assignToSection2(sect, symn, sym.SRODATA)
+		state.assignToSection(sect, symn, sym.SRODATA)
 		if ctxt.HeadType == objabi.Haix {
 			// Read-only symbols might be wrapped inside their outer
 			// symbol.
 			// XCOFF symbol table needs to know the size of
 			// these outer symbols.
-			xcoffUpdateOuterSize2(ctxt, state.datsize-symnStartValue, symn)
+			xcoffUpdateOuterSize(ctxt, state.datsize-symnStartValue, symn)
 		}
 	}
 
 	/* read-only ELF, Mach-O sections */
-	state.allocateSingleSymSections2(segro, sym.SELFROSECT, sym.SRODATA, 04)
-	state.allocateSingleSymSections2(segro, sym.SMACHOPLT, sym.SRODATA, 04)
+	state.allocateSingleSymSections(segro, sym.SELFROSECT, sym.SRODATA, 04)
+	state.allocateSingleSymSections(segro, sym.SMACHOPLT, sym.SRODATA, 04)
 
 	// There is some data that are conceptually read-only but are written to by
 	// relocations. On GNU systems, we can arrange for the dynamic linker to
@@ -1873,19 +1864,19 @@
 			symn := sym.RelROMap[symnro]
 			symnStartValue := state.datsize
 
-			for _, s := range state.data2[symn] {
+			for _, s := range state.data[symn] {
 				outer := ldr.OuterSym(s)
 				if s != 0 && ldr.SymSect(outer) != nil && ldr.SymSect(outer) != sect {
 					ctxt.Errorf(s, "s.Outer (%s) in different section from s, %s != %s", ldr.SymName(outer), ldr.SymSect(outer).Name, sect.Name)
 				}
 			}
-			state.assignToSection2(sect, symn, sym.SRODATA)
+			state.assignToSection(sect, symn, sym.SRODATA)
 			if ctxt.HeadType == objabi.Haix {
 				// Read-only symbols might be wrapped inside their outer
 				// symbol.
 				// XCOFF symbol table needs to know the size of
 				// these outer symbols.
-				xcoffUpdateOuterSize2(ctxt, state.datsize-symnStartValue, symn)
+				xcoffUpdateOuterSize(ctxt, state.datsize-symnStartValue, symn)
 			}
 		}
 
@@ -1903,22 +1894,22 @@
 	sect.Length = uint64(state.datsize) - sect.Vaddr
 
 	/* itablink */
-	sect = state.allocateNamedSectionAndAssignSyms2(seg, genrelrosecname(".itablink"), sym.SITABLINK, sym.Sxxx, relroSecPerm)
+	sect = state.allocateNamedSectionAndAssignSyms(seg, genrelrosecname(".itablink"), sym.SITABLINK, sym.Sxxx, relroSecPerm)
 	ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.itablink", 0), sect)
 	ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.eitablink", 0), sect)
 	if ctxt.HeadType == objabi.Haix {
 		// Store .itablink size because its symbols are wrapped
 		// under an outer symbol: runtime.itablink.
-		xcoffUpdateOuterSize2(ctxt, int64(sect.Length), sym.SITABLINK)
+		xcoffUpdateOuterSize(ctxt, int64(sect.Length), sym.SITABLINK)
 	}
 
 	/* gosymtab */
-	sect = state.allocateNamedSectionAndAssignSyms2(seg, genrelrosecname(".gosymtab"), sym.SSYMTAB, sym.SRODATA, relroSecPerm)
+	sect = state.allocateNamedSectionAndAssignSyms(seg, genrelrosecname(".gosymtab"), sym.SSYMTAB, sym.SRODATA, relroSecPerm)
 	ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.symtab", 0), sect)
 	ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.esymtab", 0), sect)
 
 	/* gopclntab */
-	sect = state.allocateNamedSectionAndAssignSyms2(seg, genrelrosecname(".gopclntab"), sym.SPCLNTAB, sym.SRODATA, relroSecPerm)
+	sect = state.allocateNamedSectionAndAssignSyms(seg, genrelrosecname(".gopclntab"), sym.SPCLNTAB, sym.SRODATA, relroSecPerm)
 	ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.pclntab", 0), sect)
 	ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.epclntab", 0), sect)
 
@@ -1929,35 +1920,35 @@
 
 	siz := 0
 	for symn := sym.SELFRXSECT; symn < sym.SXREF; symn++ {
-		siz += len(state.data2[symn])
+		siz += len(state.data[symn])
 	}
-	ctxt.datap2 = make([]loader.Sym, 0, siz)
+	ctxt.datap = make([]loader.Sym, 0, siz)
 	for symn := sym.SELFRXSECT; symn < sym.SXREF; symn++ {
-		ctxt.datap2 = append(ctxt.datap2, state.data2[symn]...)
+		ctxt.datap = append(ctxt.datap, state.data[symn]...)
 	}
 }
 
 // allocateDwarfSections allocates sym.Section objects for DWARF
 // symbols, and assigns symbols to sections.
-func (state *dodataState) allocateDwarfSections2(ctxt *Link) {
+func (state *dodataState) allocateDwarfSections(ctxt *Link) {
 
 	alignOne := func(state *dodataState, datsize int64, s loader.Sym) int64 { return datsize }
 
 	ldr := ctxt.loader
-	for i := 0; i < len(dwarfp2); i++ {
+	for i := 0; i < len(dwarfp); i++ {
 		// First the section symbol.
-		s := dwarfp2[i].secSym()
+		s := dwarfp[i].secSym()
 		sect := state.allocateNamedDataSection(&Segdwarf, ldr.SymName(s), []sym.SymKind{}, 04)
 		ldr.SetSymSect(s, sect)
-		sect.Sym2 = sym.LoaderSym(s)
+		sect.Sym = sym.LoaderSym(s)
 		curType := ldr.SymType(s)
 		state.setSymType(s, sym.SRODATA)
 		ldr.SetSymValue(s, int64(uint64(state.datsize)-sect.Vaddr))
 		state.datsize += ldr.SymSize(s)
 
 		// Then any sub-symbols for the section symbol.
-		subSyms := dwarfp2[i].subSyms()
-		state.assignDsymsToSection2(sect, subSyms, sym.SRODATA, alignOne)
+		subSyms := dwarfp[i].subSyms()
+		state.assignDsymsToSection(sect, subSyms, sym.SRODATA, alignOne)
 
 		for j := 0; j < len(subSyms); j++ {
 			s := subSyms[j]
@@ -1978,7 +1969,7 @@
 	sym  loader.Sym
 }
 
-func (state *dodataState) dodataSect2(ctxt *Link, symn sym.SymKind, syms []loader.Sym) (result []loader.Sym, maxAlign int32) {
+func (state *dodataState) dodataSect(ctxt *Link, symn sym.SymKind, syms []loader.Sym) (result []loader.Sym, maxAlign int32) {
 	var head, tail loader.Sym
 	ldr := ctxt.loader
 	sl := make([]symNameSize, len(syms))
@@ -2045,7 +2036,7 @@
 	for k := range sl {
 		s := sl[k].sym
 		if s != head && s != tail {
-			align := state.symalign2(s)
+			align := symalign(ldr, s)
 			if maxAlign < align {
 				maxAlign = align
 			}
@@ -2076,9 +2067,9 @@
 	s.SetData([]byte(data))
 	s.SetSize(int64(len(data)))
 
-	ctxt.Textp2 = append(ctxt.Textp2, 0)
-	copy(ctxt.Textp2[1:], ctxt.Textp2)
-	ctxt.Textp2[0] = s.Sym()
+	ctxt.Textp = append(ctxt.Textp, 0)
+	copy(ctxt.Textp[1:], ctxt.Textp)
+	ctxt.Textp[0] = s.Sym()
 }
 
 func (ctxt *Link) buildinfo() {
@@ -2093,6 +2084,9 @@
 	ldr := ctxt.loader
 	s := ldr.CreateSymForUpdate(".go.buildinfo", 0)
 	s.SetReachable(true)
+	// On AIX, .go.buildinfo must be in the symbol table as
+	// it has relocations.
+	s.SetNotInSymbolTable(!ctxt.IsAIX())
 	s.SetType(sym.SBUILDINFO)
 	s.SetAlign(16)
 	// The \xff is invalid UTF-8, meant to make it less likely
@@ -2145,16 +2139,16 @@
 		etext := ldr.LookupOrCreateSym("runtime.etext", 0)
 		ldr.SetSymSect(etext, sect)
 
-		ctxt.Textp2 = append(ctxt.Textp2, etext, 0)
-		copy(ctxt.Textp2[1:], ctxt.Textp2)
-		ctxt.Textp2[0] = text
+		ctxt.Textp = append(ctxt.Textp, etext, 0)
+		copy(ctxt.Textp[1:], ctxt.Textp)
+		ctxt.Textp[0] = text
 	}
 
 	va := uint64(*FlagTextAddr)
 	n := 1
 	sect.Vaddr = va
 	ntramps := 0
-	for _, s := range ctxt.Textp2 {
+	for _, s := range ctxt.Textp {
 		sect, n, va = assignAddress(ctxt, sect, n, s, va, false)
 
 		trampoline(ctxt, s) // resolve jumps, may add trampolines if jump too far
@@ -2177,9 +2171,9 @@
 
 	// merge tramps into Textp, keeping Textp in address order
 	if ntramps != 0 {
-		newtextp := make([]loader.Sym, 0, len(ctxt.Textp2)+ntramps)
+		newtextp := make([]loader.Sym, 0, len(ctxt.Textp)+ntramps)
 		i := 0
-		for _, s := range ctxt.Textp2 {
+		for _, s := range ctxt.Textp {
 			for ; i < ntramps && ldr.SymValue(ctxt.tramps[i]) < ldr.SymValue(s); i++ {
 				newtextp = append(newtextp, ctxt.tramps[i])
 			}
@@ -2187,7 +2181,7 @@
 		}
 		newtextp = append(newtextp, ctxt.tramps[i:ntramps]...)
 
-		ctxt.Textp2 = newtextp
+		ctxt.Textp = newtextp
 	}
 }
 
@@ -2412,7 +2406,7 @@
 		}
 	}
 
-	for _, s := range ctxt.datap2 {
+	for _, s := range ctxt.datap {
 		if sect := ldr.SymSect(s); sect != nil {
 			ldr.AddToSymValue(s, int64(sect.Vaddr))
 		}
@@ -2422,7 +2416,7 @@
 		}
 	}
 
-	for _, si := range dwarfp2 {
+	for _, si := range dwarfp {
 		for _, s := range si.syms {
 			if sect := ldr.SymSect(s); sect != nil {
 				ldr.AddToSymValue(s, int64(sect.Vaddr))
@@ -2445,8 +2439,8 @@
 		ldr.SetSymValue(s, int64(sect.Vaddr+16))
 	}
 
-	ctxt.xdefine2("runtime.text", sym.STEXT, int64(text.Vaddr))
-	ctxt.xdefine2("runtime.etext", sym.STEXT, int64(lasttext.Vaddr+lasttext.Length))
+	ctxt.xdefine("runtime.text", sym.STEXT, int64(text.Vaddr))
+	ctxt.xdefine("runtime.etext", sym.STEXT, int64(lasttext.Vaddr+lasttext.Length))
 
 	// If there are multiple text sections, create runtime.text.n for
 	// their section Vaddr, using n for index
@@ -2459,41 +2453,41 @@
 		if ctxt.HeadType != objabi.Haix || ctxt.LinkMode != LinkExternal {
 			// Addresses are already set on AIX with external linker
 			// because these symbols are part of their sections.
-			ctxt.xdefine2(symname, sym.STEXT, int64(sect.Vaddr))
+			ctxt.xdefine(symname, sym.STEXT, int64(sect.Vaddr))
 		}
 		n++
 	}
 
-	ctxt.xdefine2("runtime.rodata", sym.SRODATA, int64(rodata.Vaddr))
-	ctxt.xdefine2("runtime.erodata", sym.SRODATA, int64(rodata.Vaddr+rodata.Length))
-	ctxt.xdefine2("runtime.types", sym.SRODATA, int64(types.Vaddr))
-	ctxt.xdefine2("runtime.etypes", sym.SRODATA, int64(types.Vaddr+types.Length))
-	ctxt.xdefine2("runtime.itablink", sym.SRODATA, int64(itablink.Vaddr))
-	ctxt.xdefine2("runtime.eitablink", sym.SRODATA, int64(itablink.Vaddr+itablink.Length))
+	ctxt.xdefine("runtime.rodata", sym.SRODATA, int64(rodata.Vaddr))
+	ctxt.xdefine("runtime.erodata", sym.SRODATA, int64(rodata.Vaddr+rodata.Length))
+	ctxt.xdefine("runtime.types", sym.SRODATA, int64(types.Vaddr))
+	ctxt.xdefine("runtime.etypes", sym.SRODATA, int64(types.Vaddr+types.Length))
+	ctxt.xdefine("runtime.itablink", sym.SRODATA, int64(itablink.Vaddr))
+	ctxt.xdefine("runtime.eitablink", sym.SRODATA, int64(itablink.Vaddr+itablink.Length))
 
 	s := ldr.Lookup("runtime.gcdata", 0)
 	ldr.SetAttrLocal(s, true)
-	ctxt.xdefine2("runtime.egcdata", sym.SRODATA, ldr.SymAddr(s)+ldr.SymSize(s))
+	ctxt.xdefine("runtime.egcdata", sym.SRODATA, ldr.SymAddr(s)+ldr.SymSize(s))
 	ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.egcdata", 0), ldr.SymSect(s))
 
 	s = ldr.LookupOrCreateSym("runtime.gcbss", 0)
 	ldr.SetAttrLocal(s, true)
-	ctxt.xdefine2("runtime.egcbss", sym.SRODATA, ldr.SymAddr(s)+ldr.SymSize(s))
+	ctxt.xdefine("runtime.egcbss", sym.SRODATA, ldr.SymAddr(s)+ldr.SymSize(s))
 	ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.egcbss", 0), ldr.SymSect(s))
 
-	ctxt.xdefine2("runtime.symtab", sym.SRODATA, int64(symtab.Vaddr))
-	ctxt.xdefine2("runtime.esymtab", sym.SRODATA, int64(symtab.Vaddr+symtab.Length))
-	ctxt.xdefine2("runtime.pclntab", sym.SRODATA, int64(pclntab.Vaddr))
-	ctxt.xdefine2("runtime.epclntab", sym.SRODATA, int64(pclntab.Vaddr+pclntab.Length))
-	ctxt.xdefine2("runtime.noptrdata", sym.SNOPTRDATA, int64(noptr.Vaddr))
-	ctxt.xdefine2("runtime.enoptrdata", sym.SNOPTRDATA, int64(noptr.Vaddr+noptr.Length))
-	ctxt.xdefine2("runtime.bss", sym.SBSS, int64(bss.Vaddr))
-	ctxt.xdefine2("runtime.ebss", sym.SBSS, int64(bss.Vaddr+bss.Length))
-	ctxt.xdefine2("runtime.data", sym.SDATA, int64(data.Vaddr))
-	ctxt.xdefine2("runtime.edata", sym.SDATA, int64(data.Vaddr+data.Length))
-	ctxt.xdefine2("runtime.noptrbss", sym.SNOPTRBSS, int64(noptrbss.Vaddr))
-	ctxt.xdefine2("runtime.enoptrbss", sym.SNOPTRBSS, int64(noptrbss.Vaddr+noptrbss.Length))
-	ctxt.xdefine2("runtime.end", sym.SBSS, int64(Segdata.Vaddr+Segdata.Length))
+	ctxt.xdefine("runtime.symtab", sym.SRODATA, int64(symtab.Vaddr))
+	ctxt.xdefine("runtime.esymtab", sym.SRODATA, int64(symtab.Vaddr+symtab.Length))
+	ctxt.xdefine("runtime.pclntab", sym.SRODATA, int64(pclntab.Vaddr))
+	ctxt.xdefine("runtime.epclntab", sym.SRODATA, int64(pclntab.Vaddr+pclntab.Length))
+	ctxt.xdefine("runtime.noptrdata", sym.SNOPTRDATA, int64(noptr.Vaddr))
+	ctxt.xdefine("runtime.enoptrdata", sym.SNOPTRDATA, int64(noptr.Vaddr+noptr.Length))
+	ctxt.xdefine("runtime.bss", sym.SBSS, int64(bss.Vaddr))
+	ctxt.xdefine("runtime.ebss", sym.SBSS, int64(bss.Vaddr+bss.Length))
+	ctxt.xdefine("runtime.data", sym.SDATA, int64(data.Vaddr))
+	ctxt.xdefine("runtime.edata", sym.SDATA, int64(data.Vaddr+data.Length))
+	ctxt.xdefine("runtime.noptrbss", sym.SNOPTRBSS, int64(noptrbss.Vaddr))
+	ctxt.xdefine("runtime.enoptrbss", sym.SNOPTRBSS, int64(noptrbss.Vaddr+noptrbss.Length))
+	ctxt.xdefine("runtime.end", sym.SBSS, int64(Segdata.Vaddr+Segdata.Length))
 
 	if ctxt.IsSolaris() {
 		// On Solaris, in the runtime it sets the external names of the
@@ -2505,9 +2499,9 @@
 		ldr.SetSymExtname(etext, "runtime.etext")
 		ldr.SetSymExtname(edata, "runtime.edata")
 		ldr.SetSymExtname(end, "runtime.end")
-		ctxt.xdefine2("_etext", ldr.SymType(etext), ldr.SymValue(etext))
-		ctxt.xdefine2("_edata", ldr.SymType(edata), ldr.SymValue(edata))
-		ctxt.xdefine2("_end", ldr.SymType(end), ldr.SymValue(end))
+		ctxt.xdefine("_etext", ldr.SymType(etext), ldr.SymValue(etext))
+		ctxt.xdefine("_edata", ldr.SymType(edata), ldr.SymValue(edata))
+		ctxt.xdefine("_end", ldr.SymType(end), ldr.SymValue(end))
 		ldr.SetSymSect(ldr.Lookup("_etext", 0), ldr.SymSect(etext))
 		ldr.SetSymSect(ldr.Lookup("_edata", 0), ldr.SymSect(edata))
 		ldr.SetSymSect(ldr.Lookup("_end", 0), ldr.SymSect(end))
diff --git a/src/cmd/link/internal/ld/data2.go b/src/cmd/link/internal/ld/data2.go
deleted file mode 100644
index d4503a4..0000000
--- a/src/cmd/link/internal/ld/data2.go
+++ /dev/null
@@ -1,518 +0,0 @@
-// 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/objabi"
-	"cmd/link/internal/loader"
-	"cmd/link/internal/sym"
-	"fmt"
-	"log"
-	"strings"
-	"sync"
-)
-
-// Temporary dumping around for sym.Symbol version of helper
-// functions in dodata(), still being used for some archs/oses.
-// FIXME: get rid of this file when dodata() is completely
-// converted.
-
-func Addstring(s *sym.Symbol, str string) int64 {
-	if s.Type == 0 {
-		s.Type = sym.SNOPTRDATA
-	}
-	s.Attr |= sym.AttrReachable
-	r := s.Size
-	if s.Name == ".shstrtab" {
-		elfsetstring(s, str, int(r))
-	}
-	s.P = append(s.P, str...)
-	s.P = append(s.P, 0)
-	s.Size = int64(len(s.P))
-	return r
-}
-
-// symalign returns the required alignment for the given symbol s.
-func symalign(s *sym.Symbol) int32 {
-	min := int32(thearch.Minalign)
-	if s.Align >= min {
-		return s.Align
-	} else if s.Align != 0 {
-		return min
-	}
-	if strings.HasPrefix(s.Name, "go.string.") || strings.HasPrefix(s.Name, "type..namedata.") {
-		// String data is just bytes.
-		// If we align it, we waste a lot of space to padding.
-		return min
-	}
-	align := int32(thearch.Maxalign)
-	for int64(align) > s.Size && align > min {
-		align >>= 1
-	}
-	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
-	}
-	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.P, 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.
-			u := ldr.SymUnit(loader.Sym(r.Sym.SymIdx))
-			o = Symaddr(r.Sym) + r.Add - Symaddr(ldr.Syms[u.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))
-		}
-	}
-}
-
-func (ctxt *Link) reloc2() {
-	var wg sync.WaitGroup
-	target := &ctxt.Target
-	ldr := ctxt.loader
-	reporter := &ctxt.ErrorReporter
-	syms := &ctxt.ArchSyms
-	wg.Add(3)
-	go func() {
-		if !ctxt.IsWasm() { // On Wasm, text relocations are applied in Asmb2.
-			for _, s := range ctxt.Textp {
-				relocsym2(target, ldr, reporter, syms, s)
-			}
-		}
-		wg.Done()
-	}()
-	go func() {
-		for _, s := range ctxt.datap {
-			relocsym2(target, ldr, reporter, syms, s)
-		}
-		wg.Done()
-	}()
-	go func() {
-		for _, si := range dwarfp {
-			for _, s := range si.syms {
-				relocsym2(target, ldr, reporter, syms, s)
-			}
-		}
-		wg.Done()
-	}()
-	wg.Wait()
-}
diff --git a/src/cmd/link/internal/ld/data_test.go b/src/cmd/link/internal/ld/data_test.go
new file mode 100644
index 0000000..7c46307
--- /dev/null
+++ b/src/cmd/link/internal/ld/data_test.go
@@ -0,0 +1,92 @@
+// 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/objabi"
+	"cmd/internal/sys"
+	"cmd/link/internal/loader"
+	"testing"
+)
+
+func setUpContext(arch *sys.Arch, iself bool, ht objabi.HeadType, bm, lm string) *Link {
+	ctxt := linknew(arch)
+	edummy := func(str string, off int) {}
+	ctxt.HeadType = ht
+	er := loader.ErrorReporter{}
+	ctxt.loader = loader.NewLoader(0, edummy, &er)
+	ctxt.BuildMode.Set(bm)
+	ctxt.LinkMode.Set(lm)
+	ctxt.IsELF = iself
+	ctxt.mustSetHeadType()
+	ctxt.setArchSyms()
+	return ctxt
+}
+
+// Make sure the addgotsym properly increases the symbols.
+func TestAddGotSym(t *testing.T) {
+	tests := []struct {
+		arch    *sys.Arch
+		ht      objabi.HeadType
+		bm, lm  string
+		rel     string
+		relsize int
+		gotsize int
+	}{
+		{
+			arch:    sys.Arch386,
+			ht:      objabi.Hlinux,
+			bm:      "pie",
+			lm:      "internal",
+			rel:     ".rel",
+			relsize: 2 * sys.Arch386.PtrSize,
+			gotsize: sys.Arch386.PtrSize,
+		},
+		{
+			arch:    sys.ArchAMD64,
+			ht:      objabi.Hlinux,
+			bm:      "pie",
+			lm:      "internal",
+			rel:     ".rela",
+			relsize: 3 * sys.ArchAMD64.PtrSize,
+			gotsize: sys.ArchAMD64.PtrSize,
+		},
+		{
+			arch:    sys.ArchAMD64,
+			ht:      objabi.Hdarwin,
+			bm:      "pie",
+			lm:      "external",
+			gotsize: sys.ArchAMD64.PtrSize,
+		},
+	}
+
+	// Save the architecture as we're going to set it on each test run.
+	origArch := objabi.GOARCH
+	defer func() {
+		objabi.GOARCH = origArch
+	}()
+
+	for i, test := range tests {
+		iself := len(test.rel) != 0
+		objabi.GOARCH = test.arch.Name
+		ctxt := setUpContext(test.arch, iself, test.ht, test.bm, test.lm)
+		foo := ctxt.loader.CreateSymForUpdate("foo", 0)
+		ctxt.loader.CreateExtSym("bar", 0)
+		AddGotSym(&ctxt.Target, ctxt.loader, &ctxt.ArchSyms, foo.Sym(), 0)
+
+		if iself {
+			rel := ctxt.loader.Lookup(test.rel, 0)
+			if rel == 0 {
+				t.Fatalf("[%d] could not find symbol: %q", i, test.rel)
+			}
+			if s := ctxt.loader.SymSize(rel); s != int64(test.relsize) {
+				t.Fatalf("[%d] expected ldr.Size(%q) == %v, got %v", i, test.rel, test.relsize, s)
+			}
+		}
+		if s := ctxt.loader.SymSize(ctxt.loader.Lookup(".got", 0)); s != int64(test.gotsize) {
+			t.Fatalf(`[%d] expected ldr.Size(".got") == %v, got %v`, i, test.gotsize, s)
+		}
+	}
+}
diff --git a/src/cmd/link/internal/ld/deadcode.go b/src/cmd/link/internal/ld/deadcode.go
index 7c58a62..d59b1f2 100644
--- a/src/cmd/link/internal/ld/deadcode.go
+++ b/src/cmd/link/internal/ld/deadcode.go
@@ -5,42 +5,27 @@
 package ld
 
 import (
-	"bytes"
 	"cmd/internal/goobj2"
 	"cmd/internal/objabi"
 	"cmd/internal/sys"
 	"cmd/link/internal/loader"
 	"cmd/link/internal/sym"
-	"container/heap"
 	"fmt"
 	"unicode"
 )
 
 var _ = fmt.Print
 
-type workQueue []loader.Sym
-
-// Implement container/heap.Interface.
-func (q *workQueue) Len() int           { return len(*q) }
-func (q *workQueue) Less(i, j int) bool { return (*q)[i] < (*q)[j] }
-func (q *workQueue) Swap(i, j int)      { (*q)[i], (*q)[j] = (*q)[j], (*q)[i] }
-func (q *workQueue) Push(i interface{}) { *q = append(*q, i.(loader.Sym)) }
-func (q *workQueue) Pop() interface{}   { i := (*q)[len(*q)-1]; *q = (*q)[:len(*q)-1]; return i }
-
-// Functions for deadcode pass to use.
-// Deadcode pass should call push/pop, not Push/Pop.
-func (q *workQueue) push(i loader.Sym) { heap.Push(q, i) }
-func (q *workQueue) pop() loader.Sym   { return heap.Pop(q).(loader.Sym) }
-func (q *workQueue) empty() bool       { return len(*q) == 0 }
-
 type deadcodePass struct {
 	ctxt *Link
 	ldr  *loader.Loader
-	wq   workQueue
+	wq   heap // work queue, using min-heap for beter locality
 
 	ifaceMethod     map[methodsig]bool // methods declared in reached interfaces
 	markableMethods []methodref        // methods of reached types
 	reflectSeen     bool               // whether we have seen a reflect method call
+
+	methodsigstmp []methodsig // scratch buffer for decoding method signatures
 }
 
 func (d *deadcodePass) init() {
@@ -49,7 +34,6 @@
 	if objabi.Fieldtrack_enabled != 0 {
 		d.ldr.Reachparent = make([]loader.Sym, d.ldr.NSym())
 	}
-	heap.Init(&d.wq)
 
 	if d.ctxt.BuildMode == BuildModeShared {
 		// Mark all symbols defined in this library as reachable when
@@ -110,6 +94,7 @@
 }
 
 func (d *deadcodePass) flood() {
+	var methods []methodref
 	for !d.wq.empty() {
 		symIdx := d.wq.pop()
 
@@ -123,14 +108,14 @@
 			if len(p) != 0 && decodetypeKind(d.ctxt.Arch, p)&kindMask == kindInterface {
 				for _, sig := range d.decodeIfaceMethods(d.ldr, d.ctxt.Arch, symIdx, &relocs) {
 					if d.ctxt.Debugvlog > 1 {
-						d.ctxt.Logf("reached iface method: %s\n", sig)
+						d.ctxt.Logf("reached iface method: %v\n", sig)
 					}
 					d.ifaceMethod[sig] = true
 				}
 			}
 		}
 
-		var methods []methodref
+		methods = methods[:0]
 		for i := 0; i < relocs.Count(); i++ {
 			r := relocs.At2(i)
 			t := r.Type()
@@ -191,6 +176,9 @@
 			}
 			for i, m := range methodsigs {
 				methods[i].m = m
+				if d.ctxt.Debugvlog > 1 {
+					d.ctxt.Logf("markable method: %v of sym %v %s\n", m, symIdx, d.ldr.SymName(symIdx))
+				}
 			}
 			d.markableMethods = append(d.markableMethods, methods...)
 		}
@@ -316,6 +304,12 @@
 	}
 }
 
+// methodsig is a typed method signature (name + type).
+type methodsig struct {
+	name string
+	typ  loader.Sym // type descriptor symbol of the function
+}
+
 // methodref holds the relocations from a receiver type symbol to its
 // method. There are three relocations, one for each of the fields in
 // the reflect.method struct: mtyp, ifn, and tfn.
@@ -326,52 +320,27 @@
 }
 
 func (m methodref) isExported() bool {
-	for _, r := range m.m {
+	for _, r := range m.m.name {
 		return unicode.IsUpper(r)
 	}
 	panic("methodref has no signature")
 }
 
-// decodeMethodSig2 decodes an array of method signature information.
+// decodeMethodSig decodes an array of method signature information.
 // Each element of the array is size bytes. The first 4 bytes is a
 // nameOff for the method name, and the next 4 bytes is a typeOff for
 // the function type.
 //
 // Conveniently this is the layout of both runtime.method and runtime.imethod.
 func (d *deadcodePass) decodeMethodSig(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym, relocs *loader.Relocs, off, size, count int) []methodsig {
-	var buf bytes.Buffer
-	var methods []methodsig
+	if cap(d.methodsigstmp) < count {
+		d.methodsigstmp = append(d.methodsigstmp[:0], make([]methodsig, count)...)
+	}
+	var methods = d.methodsigstmp[:count]
 	for i := 0; i < count; i++ {
-		buf.WriteString(decodetypeName(ldr, symIdx, relocs, off))
-		mtypSym := decodeRelocSym(ldr, symIdx, relocs, int32(off+4))
-		// FIXME: add some sort of caching here, since we may see some of the
-		// same symbols over time for param types.
-		mrelocs := ldr.Relocs(mtypSym)
-		mp := ldr.Data(mtypSym)
-
-		buf.WriteRune('(')
-		inCount := decodetypeFuncInCount(arch, mp)
-		for i := 0; i < inCount; i++ {
-			if i > 0 {
-				buf.WriteString(", ")
-			}
-			a := decodetypeFuncInType(ldr, arch, mtypSym, &mrelocs, i)
-			buf.WriteString(ldr.SymName(a))
-		}
-		buf.WriteString(") (")
-		outCount := decodetypeFuncOutCount(arch, mp)
-		for i := 0; i < outCount; i++ {
-			if i > 0 {
-				buf.WriteString(", ")
-			}
-			a := decodetypeFuncOutType(ldr, arch, mtypSym, &mrelocs, i)
-			buf.WriteString(ldr.SymName(a))
-		}
-		buf.WriteRune(')')
-
+		methods[i].name = decodetypeName(ldr, symIdx, relocs, off)
+		methods[i].typ = decodeRelocSym(ldr, symIdx, relocs, int32(off+4))
 		off += size
-		methods = append(methods, methodsig(buf.String()))
-		buf.Reset()
 	}
 	return methods
 }
diff --git a/src/cmd/link/internal/ld/decodesym.go b/src/cmd/link/internal/ld/decodesym.go
index e9c87ef..3211a4e 100644
--- a/src/cmd/link/internal/ld/decodesym.go
+++ b/src/cmd/link/internal/ld/decodesym.go
@@ -90,10 +90,6 @@
 	return int64(decodeInuxi(arch, p[commonsize(arch)+2*arch.PtrSize:], arch.PtrSize))
 }
 
-// methodsig is a fully qualified typed method signature, like
-// "Visit(type.go/ast.Node) (type.go/ast.Visitor)".
-type methodsig string
-
 // Matches runtime/typekind.go and reflect.Kind.
 const (
 	kindArray     = 17
diff --git a/src/cmd/link/internal/ld/dwarf.go b/src/cmd/link/internal/ld/dwarf.go
index 8df03d7..617f968 100644
--- a/src/cmd/link/internal/ld/dwarf.go
+++ b/src/cmd/link/internal/ld/dwarf.go
@@ -27,13 +27,13 @@
 	"strings"
 )
 
-// dwctxt2 is a wrapper intended to satisfy the method set of
+// dwctxt is a wrapper intended to satisfy the method set of
 // dwarf.Context, so that functions like dwarf.PutAttrs will work with
 // DIEs that use loader.Sym as opposed to *sym.Symbol. It is also
 // being used as a place to store tables/maps that are useful as part
 // of type conversion (this is just a convenience; it would be easy to
 // split these things out into another type if need be).
-type dwctxt2 struct {
+type dwctxt struct {
 	linkctxt *Link
 	ldr      *loader.Loader
 	arch     *sys.Arch
@@ -59,8 +59,8 @@
 	uintptrInfoSym   loader.Sym
 }
 
-func newdwctxt2(linkctxt *Link, forTypeGen bool) dwctxt2 {
-	d := dwctxt2{
+func newdwctxt(linkctxt *Link, forTypeGen bool) dwctxt {
+	d := dwctxt{
 		linkctxt: linkctxt,
 		ldr:      linkctxt.loader,
 		arch:     linkctxt.Arch,
@@ -79,33 +79,33 @@
 type dwSym loader.Sym
 
 func (s dwSym) Length(dwarfContext interface{}) int64 {
-	l := dwarfContext.(dwctxt2).ldr
+	l := dwarfContext.(dwctxt).ldr
 	return int64(len(l.Data(loader.Sym(s))))
 }
 
-func (c dwctxt2) PtrSize() int {
+func (c dwctxt) PtrSize() int {
 	return c.arch.PtrSize
 }
 
-func (c dwctxt2) AddInt(s dwarf.Sym, size int, i int64) {
+func (c dwctxt) AddInt(s dwarf.Sym, size int, i int64) {
 	ds := loader.Sym(s.(dwSym))
 	dsu := c.ldr.MakeSymbolUpdater(ds)
 	dsu.AddUintXX(c.arch, uint64(i), size)
 }
 
-func (c dwctxt2) AddBytes(s dwarf.Sym, b []byte) {
+func (c dwctxt) AddBytes(s dwarf.Sym, b []byte) {
 	ds := loader.Sym(s.(dwSym))
 	dsu := c.ldr.MakeSymbolUpdater(ds)
 	dsu.AddBytes(b)
 }
 
-func (c dwctxt2) AddString(s dwarf.Sym, v string) {
+func (c dwctxt) AddString(s dwarf.Sym, v string) {
 	ds := loader.Sym(s.(dwSym))
 	dsu := c.ldr.MakeSymbolUpdater(ds)
 	dsu.Addstring(v)
 }
 
-func (c dwctxt2) AddAddress(s dwarf.Sym, data interface{}, value int64) {
+func (c dwctxt) AddAddress(s dwarf.Sym, data interface{}, value int64) {
 	ds := loader.Sym(s.(dwSym))
 	dsu := c.ldr.MakeSymbolUpdater(ds)
 	if value != 0 {
@@ -115,7 +115,7 @@
 	dsu.AddAddrPlus(c.arch, tgtds, value)
 }
 
-func (c dwctxt2) AddCURelativeAddress(s dwarf.Sym, data interface{}, value int64) {
+func (c dwctxt) AddCURelativeAddress(s dwarf.Sym, data interface{}, value int64) {
 	ds := loader.Sym(s.(dwSym))
 	dsu := c.ldr.MakeSymbolUpdater(ds)
 	if value != 0 {
@@ -125,7 +125,7 @@
 	dsu.AddCURelativeAddrPlus(c.arch, tgtds, value)
 }
 
-func (c dwctxt2) AddSectionOffset(s dwarf.Sym, size int, t interface{}, ofs int64) {
+func (c dwctxt) AddSectionOffset(s dwarf.Sym, size int, t interface{}, ofs int64) {
 	ds := loader.Sym(s.(dwSym))
 	dsu := c.ldr.MakeSymbolUpdater(ds)
 	tds := loader.Sym(t.(dwSym))
@@ -137,7 +137,7 @@
 	dsu.AddSymRef(c.arch, tds, ofs, objabi.R_ADDROFF, size)
 }
 
-func (c dwctxt2) AddDWARFAddrSectionOffset(s dwarf.Sym, t interface{}, ofs int64) {
+func (c dwctxt) AddDWARFAddrSectionOffset(s dwarf.Sym, t interface{}, ofs int64) {
 	size := 4
 	if isDwarf64(c.linkctxt) {
 		size = 8
@@ -153,25 +153,25 @@
 	dsu.AddSymRef(c.arch, tds, ofs, objabi.R_DWARFSECREF, size)
 }
 
-func (c dwctxt2) Logf(format string, args ...interface{}) {
+func (c dwctxt) Logf(format string, args ...interface{}) {
 	c.linkctxt.Logf(format, args...)
 }
 
 // At the moment these interfaces are only used in the compiler.
 
-func (c dwctxt2) AddFileRef(s dwarf.Sym, f interface{}) {
+func (c dwctxt) AddFileRef(s dwarf.Sym, f interface{}) {
 	panic("should be used only in the compiler")
 }
 
-func (c dwctxt2) CurrentOffset(s dwarf.Sym) int64 {
+func (c dwctxt) CurrentOffset(s dwarf.Sym) int64 {
 	panic("should be used only in the compiler")
 }
 
-func (c dwctxt2) RecordDclReference(s dwarf.Sym, t dwarf.Sym, dclIdx int, inlIndex int) {
+func (c dwctxt) RecordDclReference(s dwarf.Sym, t dwarf.Sym, dclIdx int, inlIndex int) {
 	panic("should be used only in the compiler")
 }
 
-func (c dwctxt2) RecordChildDieOffsets(s dwarf.Sym, vars []*dwarf.Var, offsets []int32) {
+func (c dwctxt) RecordChildDieOffsets(s dwarf.Sym, vars []*dwarf.Var, offsets []int32) {
 	panic("should be used only in the compiler")
 }
 
@@ -207,11 +207,11 @@
 	return dsi.syms[1:]
 }
 
-// dwarfp2 stores the collected DWARF symbols created during
+// dwarfp stores the collected DWARF symbols created during
 // dwarf generation.
-var dwarfp2 []dwarfSecInfo
+var dwarfp []dwarfSecInfo
 
-func (d *dwctxt2) writeabbrev() dwarfSecInfo {
+func (d *dwctxt) writeabbrev() dwarfSecInfo {
 	abrvs := d.ldr.LookupOrCreateSym(".debug_abbrev", 0)
 	u := d.ldr.MakeSymbolUpdater(abrvs)
 	u.SetType(sym.SDWARFSECT)
@@ -269,7 +269,7 @@
 // The compiler does create nameless DWARF DIEs (ex: concrete subprogram
 // instance).
 // FIXME: it would be more efficient to bulk-allocate DIEs.
-func (d *dwctxt2) newdie(parent *dwarf.DWDie, abbrev int, name string, version int) *dwarf.DWDie {
+func (d *dwctxt) newdie(parent *dwarf.DWDie, abbrev int, name string, version int) *dwarf.DWDie {
 	die := new(dwarf.DWDie)
 	die.Abbrev = abbrev
 	die.Link = parent.Child
@@ -277,24 +277,37 @@
 
 	newattr(die, dwarf.DW_AT_name, dwarf.DW_CLS_STRING, int64(len(name)), name)
 
-	if name != "" && (abbrev <= dwarf.DW_ABRV_VARIABLE || abbrev >= dwarf.DW_ABRV_NULLTYPE) {
-		// Q: do we need version here? My understanding is that all these
-		// symbols should be version 0.
-		if abbrev != dwarf.DW_ABRV_VARIABLE || version == 0 {
-			if abbrev == dwarf.DW_ABRV_COMPUNIT {
-				// Avoid collisions with "real" symbol names.
-				name = fmt.Sprintf(".pkg.%s.%d", name, len(d.linkctxt.compUnits))
-			}
-			ds := d.ldr.LookupOrCreateSym(dwarf.InfoPrefix+name, version)
-			dsu := d.ldr.MakeSymbolUpdater(ds)
-			dsu.SetType(sym.SDWARFINFO)
-			d.ldr.SetAttrNotInSymbolTable(ds, true)
-			d.ldr.SetAttrReachable(ds, true)
-			die.Sym = dwSym(ds)
-			if abbrev >= dwarf.DW_ABRV_NULLTYPE && abbrev <= dwarf.DW_ABRV_TYPEDECL {
-				d.tmap[name] = ds
-			}
-		}
+	// Sanity check: all DIEs created in the linker should have a non-empty
+	// name and be version zero.
+	if name == "" || version != 0 {
+		panic("nameless or version non-zero DWARF DIE")
+	}
+
+	var st sym.SymKind
+	switch abbrev {
+	case dwarf.DW_ABRV_FUNCTYPEPARAM, dwarf.DW_ABRV_DOTDOTDOT, dwarf.DW_ABRV_STRUCTFIELD, dwarf.DW_ABRV_ARRAYRANGE:
+		// There are no relocations against these dies, and their names
+		// are not unique, so don't create a symbol.
+		return die
+	case dwarf.DW_ABRV_COMPUNIT, dwarf.DW_ABRV_COMPUNIT_TEXTLESS:
+		// Avoid collisions with "real" symbol names.
+		name = fmt.Sprintf(".pkg.%s.%d", name, len(d.linkctxt.compUnits))
+		st = sym.SDWARFCUINFO
+	case dwarf.DW_ABRV_VARIABLE:
+		st = sym.SDWARFVAR
+	default:
+		// Everything else is assigned a type of SDWARFTYPE. that
+		// this also includes loose ends such as STRUCT_FIELD.
+		st = sym.SDWARFTYPE
+	}
+	ds := d.ldr.LookupOrCreateSym(dwarf.InfoPrefix+name, version)
+	dsu := d.ldr.MakeSymbolUpdater(ds)
+	dsu.SetType(st)
+	d.ldr.SetAttrNotInSymbolTable(ds, true)
+	d.ldr.SetAttrReachable(ds, true)
+	die.Sym = dwSym(ds)
+	if abbrev >= dwarf.DW_ABRV_NULLTYPE && abbrev <= dwarf.DW_ABRV_TYPEDECL {
+		d.tmap[name] = ds
 	}
 
 	return die
@@ -316,7 +329,7 @@
 	return die
 }
 
-func (d *dwctxt2) walksymtypedef(symIdx loader.Sym) loader.Sym {
+func (d *dwctxt) walksymtypedef(symIdx loader.Sym) loader.Sym {
 
 	// We're being given the loader symbol for the type DIE, e.g.
 	// "go.info.type.uintptr". Map that first to the type symbol (e.g.
@@ -349,16 +362,13 @@
 	return nil
 }
 
-// Used to avoid string allocation when looking up dwarf symbols
-var prefixBuf = []byte(dwarf.InfoPrefix)
-
 // find looks up the loader symbol for the DWARF DIE generated for the
 // type with the specified name.
-func (d *dwctxt2) find(name string) loader.Sym {
+func (d *dwctxt) find(name string) loader.Sym {
 	return d.tmap[name]
 }
 
-func (d *dwctxt2) mustFind(name string) loader.Sym {
+func (d *dwctxt) mustFind(name string) loader.Sym {
 	r := d.find(name)
 	if r == 0 {
 		Exitf("dwarf find: cannot find %s", name)
@@ -366,7 +376,7 @@
 	return r
 }
 
-func (d *dwctxt2) adddwarfref(sb *loader.SymbolBuilder, t loader.Sym, size int) int64 {
+func (d *dwctxt) adddwarfref(sb *loader.SymbolBuilder, t loader.Sym, size int) int64 {
 	var result int64
 	switch size {
 	default:
@@ -377,14 +387,14 @@
 	return result
 }
 
-func (d *dwctxt2) newrefattr(die *dwarf.DWDie, attr uint16, ref loader.Sym) *dwarf.DWAttr {
+func (d *dwctxt) newrefattr(die *dwarf.DWDie, attr uint16, ref loader.Sym) *dwarf.DWAttr {
 	if ref == 0 {
 		return nil
 	}
 	return newattr(die, attr, dwarf.DW_CLS_REFERENCE, 0, dwSym(ref))
 }
 
-func (d *dwctxt2) dtolsym(s dwarf.Sym) loader.Sym {
+func (d *dwctxt) dtolsym(s dwarf.Sym) loader.Sym {
 	if s == nil {
 		return 0
 	}
@@ -392,7 +402,7 @@
 	return dws
 }
 
-func (d *dwctxt2) putdie(syms []loader.Sym, die *dwarf.DWDie) []loader.Sym {
+func (d *dwctxt) putdie(syms []loader.Sym, die *dwarf.DWDie) []loader.Sym {
 	s := d.dtolsym(die.Sym)
 	if s == 0 {
 		s = syms[len(syms)-1]
@@ -444,11 +454,11 @@
 
 // GDB doesn't like FORM_addr for AT_location, so emit a
 // location expression that evals to a const.
-func (d *dwctxt2) newabslocexprattr(die *dwarf.DWDie, addr int64, symIdx loader.Sym) {
+func (d *dwctxt) newabslocexprattr(die *dwarf.DWDie, addr int64, symIdx loader.Sym) {
 	newattr(die, dwarf.DW_AT_location, dwarf.DW_CLS_ADDRESS, addr, dwSym(symIdx))
 }
 
-func (d *dwctxt2) lookupOrDiag(n string) loader.Sym {
+func (d *dwctxt) lookupOrDiag(n string) loader.Sym {
 	symIdx := d.ldr.Lookup(n, 0)
 	if symIdx == 0 {
 		Exitf("dwarf: missing type: %s", n)
@@ -460,7 +470,7 @@
 	return symIdx
 }
 
-func (d *dwctxt2) dotypedef(parent *dwarf.DWDie, gotype loader.Sym, name string, def *dwarf.DWDie) *dwarf.DWDie {
+func (d *dwctxt) dotypedef(parent *dwarf.DWDie, gotype loader.Sym, name string, def *dwarf.DWDie) *dwarf.DWDie {
 	// Only emit typedefs for real names.
 	if strings.HasPrefix(name, "map[") {
 		return nil
@@ -483,7 +493,7 @@
 	// to be an anonymous symbol (we want this for perf reasons).
 	tds := d.ldr.CreateExtSym("", 0)
 	tdsu := d.ldr.MakeSymbolUpdater(tds)
-	tdsu.SetType(sym.SDWARFINFO)
+	tdsu.SetType(sym.SDWARFTYPE)
 	def.Sym = dwSym(tds)
 	d.ldr.SetAttrNotInSymbolTable(tds, true)
 	d.ldr.SetAttrReachable(tds, true)
@@ -500,7 +510,7 @@
 }
 
 // Define gotype, for composite ones recurse into constituents.
-func (d *dwctxt2) defgotype(gotype loader.Sym) loader.Sym {
+func (d *dwctxt) defgotype(gotype loader.Sym) loader.Sym {
 	if gotype == 0 {
 		return d.mustFind("<unspecified>")
 	}
@@ -527,7 +537,7 @@
 	return loader.Sym(gtdwSym.Sym.(dwSym))
 }
 
-func (d *dwctxt2) newtype(gotype loader.Sym) *dwarf.DWDie {
+func (d *dwctxt) newtype(gotype loader.Sym) *dwarf.DWDie {
 	sn := d.ldr.SymName(gotype)
 	name := sn[5:] // could also decode from Type.string
 	tdata := d.ldr.Data(gotype)
@@ -717,12 +727,12 @@
 	return die
 }
 
-func (d *dwctxt2) nameFromDIESym(dwtypeDIESym loader.Sym) string {
+func (d *dwctxt) nameFromDIESym(dwtypeDIESym loader.Sym) string {
 	sn := d.ldr.SymName(dwtypeDIESym)
 	return sn[len(dwarf.InfoPrefix):]
 }
 
-func (d *dwctxt2) defptrto(dwtype loader.Sym) loader.Sym {
+func (d *dwctxt) defptrto(dwtype loader.Sym) loader.Sym {
 
 	// FIXME: it would be nice if the compiler attached an aux symbol
 	// ref from the element type to the pointer type -- it would be
@@ -756,7 +766,7 @@
 // Copies src's children into dst. Copies attributes by value.
 // DWAttr.data is copied as pointer only. If except is one of
 // the top-level children, it will not be copied.
-func (d *dwctxt2) copychildrenexcept(ctxt *Link, dst *dwarf.DWDie, src *dwarf.DWDie, except *dwarf.DWDie) {
+func (d *dwctxt) copychildrenexcept(ctxt *Link, dst *dwarf.DWDie, src *dwarf.DWDie, except *dwarf.DWDie) {
 	for src = src.Child; src != nil; src = src.Link {
 		if src == except {
 			continue
@@ -771,13 +781,13 @@
 	reverselist(&dst.Child)
 }
 
-func (d *dwctxt2) copychildren(ctxt *Link, dst *dwarf.DWDie, src *dwarf.DWDie) {
+func (d *dwctxt) copychildren(ctxt *Link, dst *dwarf.DWDie, src *dwarf.DWDie) {
 	d.copychildrenexcept(ctxt, dst, src, nil)
 }
 
 // Search children (assumed to have TAG_member) for the one named
 // field and set its AT_type to dwtype
-func (d *dwctxt2) substitutetype(structdie *dwarf.DWDie, field string, dwtype loader.Sym) {
+func (d *dwctxt) substitutetype(structdie *dwarf.DWDie, field string, dwtype loader.Sym) {
 	child := findchild(structdie, field)
 	if child == nil {
 		Exitf("dwarf substitutetype: %s does not have member %s",
@@ -793,7 +803,7 @@
 	}
 }
 
-func (d *dwctxt2) findprotodie(ctxt *Link, name string) *dwarf.DWDie {
+func (d *dwctxt) findprotodie(ctxt *Link, name string) *dwarf.DWDie {
 	die, ok := prototypedies[name]
 	if ok && die == nil {
 		d.defgotype(d.lookupOrDiag(name))
@@ -805,7 +815,7 @@
 	return die
 }
 
-func (d *dwctxt2) synthesizestringtypes(ctxt *Link, die *dwarf.DWDie) {
+func (d *dwctxt) synthesizestringtypes(ctxt *Link, die *dwarf.DWDie) {
 	prototype := walktypedef(d.findprotodie(ctxt, "type.runtime.stringStructDWARF"))
 	if prototype == nil {
 		return
@@ -819,7 +829,7 @@
 	}
 }
 
-func (d *dwctxt2) synthesizeslicetypes(ctxt *Link, die *dwarf.DWDie) {
+func (d *dwctxt) synthesizeslicetypes(ctxt *Link, die *dwarf.DWDie) {
 	prototype := walktypedef(d.findprotodie(ctxt, "type.runtime.slice"))
 	if prototype == nil {
 		return
@@ -849,11 +859,11 @@
 	BucketSize = 8
 )
 
-func (d *dwctxt2) mkinternaltype(ctxt *Link, abbrev int, typename, keyname, valname string, f func(*dwarf.DWDie)) loader.Sym {
+func (d *dwctxt) mkinternaltype(ctxt *Link, abbrev int, typename, keyname, valname string, f func(*dwarf.DWDie)) loader.Sym {
 	name := mkinternaltypename(typename, keyname, valname)
 	symname := dwarf.InfoPrefix + name
 	s := d.ldr.Lookup(symname, 0)
-	if s != 0 && d.ldr.SymType(s) == sym.SDWARFINFO {
+	if s != 0 && d.ldr.SymType(s) == sym.SDWARFTYPE {
 		return s
 	}
 	die := d.newdie(&dwtypes, abbrev, name, 0)
@@ -861,7 +871,7 @@
 	return d.dtolsym(die.Sym)
 }
 
-func (d *dwctxt2) synthesizemaptypes(ctxt *Link, die *dwarf.DWDie) {
+func (d *dwctxt) synthesizemaptypes(ctxt *Link, die *dwarf.DWDie) {
 	hash := walktypedef(d.findprotodie(ctxt, "type.runtime.hmap"))
 	bucket := walktypedef(d.findprotodie(ctxt, "type.runtime.bmap"))
 
@@ -957,7 +967,7 @@
 	}
 }
 
-func (d *dwctxt2) synthesizechantypes(ctxt *Link, die *dwarf.DWDie) {
+func (d *dwctxt) synthesizechantypes(ctxt *Link, die *dwarf.DWDie) {
 	sudog := walktypedef(d.findprotodie(ctxt, "type.runtime.sudog"))
 	waitq := walktypedef(d.findprotodie(ctxt, "type.runtime.waitq"))
 	hchan := walktypedef(d.findprotodie(ctxt, "type.runtime.hchan"))
@@ -1004,7 +1014,7 @@
 	}
 }
 
-func (d *dwctxt2) dwarfDefineGlobal(ctxt *Link, symIdx loader.Sym, str string, v int64, gotype loader.Sym) {
+func (d *dwctxt) dwarfDefineGlobal(ctxt *Link, symIdx loader.Sym, str string, v int64, gotype loader.Sym) {
 	// Find a suitable CU DIE to include the global.
 	// One would think it's as simple as just looking at the unit, but that might
 	// not have any reachable code. So, we go to the runtime's CU if our unit
@@ -1025,7 +1035,7 @@
 
 // createUnitLength creates the initial length field with value v and update
 // offset of unit_length if needed.
-func (d *dwctxt2) createUnitLength(su *loader.SymbolBuilder, v uint64) {
+func (d *dwctxt) createUnitLength(su *loader.SymbolBuilder, v uint64) {
 	if isDwarf64(d.linkctxt) {
 		su.AddUint32(d.arch, 0xFFFFFFFF)
 	}
@@ -1033,7 +1043,7 @@
 }
 
 // addDwarfAddrField adds a DWARF field in DWARF 64bits or 32bits.
-func (d *dwctxt2) addDwarfAddrField(sb *loader.SymbolBuilder, v uint64) {
+func (d *dwctxt) addDwarfAddrField(sb *loader.SymbolBuilder, v uint64) {
 	if isDwarf64(d.linkctxt) {
 		sb.AddUint(d.arch, v)
 	} else {
@@ -1042,7 +1052,7 @@
 }
 
 // addDwarfAddrRef adds a DWARF pointer in DWARF 64bits or 32bits.
-func (d *dwctxt2) addDwarfAddrRef(sb *loader.SymbolBuilder, t loader.Sym) {
+func (d *dwctxt) addDwarfAddrRef(sb *loader.SymbolBuilder, t loader.Sym) {
 	if isDwarf64(d.linkctxt) {
 		d.adddwarfref(sb, t, 8)
 	} else {
@@ -1051,9 +1061,9 @@
 }
 
 // calcCompUnitRanges calculates the PC ranges of the compilation units.
-func (d *dwctxt2) calcCompUnitRanges() {
+func (d *dwctxt) calcCompUnitRanges() {
 	var prevUnit *sym.CompilationUnit
-	for _, s := range d.linkctxt.Textp2 {
+	for _, s := range d.linkctxt.Textp {
 		sym := loader.Sym(s)
 
 		fi := d.ldr.FuncInfo(sym)
@@ -1076,7 +1086,7 @@
 		// only create boundaries between symbols from
 		// different units.
 		sval := d.ldr.SymValue(sym)
-		u0val := d.ldr.SymValue(loader.Sym(unit.Textp2[0]))
+		u0val := d.ldr.SymValue(loader.Sym(unit.Textp[0]))
 		if prevUnit != unit {
 			unit.PCs = append(unit.PCs, dwarf.Range{Start: sval - u0val})
 			prevUnit = unit
@@ -1122,10 +1132,11 @@
 	return "."
 }
 
-func (d *dwctxt2) importInfoSymbol(ctxt *Link, dsym loader.Sym) {
+func (d *dwctxt) importInfoSymbol(dsym loader.Sym) {
 	d.ldr.SetAttrReachable(dsym, true)
 	d.ldr.SetAttrNotInSymbolTable(dsym, true)
-	if d.ldr.SymType(dsym) != sym.SDWARFINFO {
+	dst := d.ldr.SymType(dsym)
+	if dst != sym.SDWARFCONST && dst != sym.SDWARFABSFCN {
 		log.Fatalf("error: DWARF info sym %d/%s with incorrect type %s", dsym, d.ldr.SymName(dsym), d.ldr.SymType(dsym).String())
 	}
 	relocs := d.ldr.Relocs(dsym)
@@ -1157,11 +1168,7 @@
 	return expandGoroot(fname)
 }
 
-func expandFileSym(l *loader.Loader, fsym loader.Sym) string {
-	return expandFile(l.SymName(fsym))
-}
-
-func (d *dwctxt2) writelines(unit *sym.CompilationUnit, ls loader.Sym) {
+func (d *dwctxt) writelines(unit *sym.CompilationUnit, ls loader.Sym) {
 
 	is_stmt := uint8(1) // initially = recommended default_is_stmt = 1, tracks is_stmt toggles.
 
@@ -1237,7 +1244,7 @@
 
 	// Output the state machine for each function remaining.
 	var lastAddr int64
-	for _, s := range unit.Textp2 {
+	for _, s := range unit.Textp {
 		fnSym := loader.Sym(s)
 
 		// Set the PC.
@@ -1293,7 +1300,7 @@
 }
 
 // writepcranges generates the DW_AT_ranges table for compilation unit cu.
-func (d *dwctxt2) writepcranges(unit *sym.CompilationUnit, base loader.Sym, pcs []dwarf.Range, ranges loader.Sym) {
+func (d *dwctxt) writepcranges(unit *sym.CompilationUnit, base loader.Sym, pcs []dwarf.Range, ranges loader.Sym) {
 
 	rsu := d.ldr.MakeSymbolUpdater(ranges)
 	rDwSym := dwSym(ranges)
@@ -1338,7 +1345,7 @@
 	return b
 }
 
-func (d *dwctxt2) writeframes() dwarfSecInfo {
+func (d *dwctxt) writeframes() dwarfSecInfo {
 	fs := d.ldr.LookupOrCreateSym(".debug_frame", 0)
 	fsd := dwSym(fs)
 	fsu := d.ldr.MakeSymbolUpdater(fs)
@@ -1400,7 +1407,7 @@
 
 	var deltaBuf []byte
 	pcsp := obj.NewPCIter(uint32(d.arch.MinLC))
-	for _, s := range d.linkctxt.Textp2 {
+	for _, s := range d.linkctxt.Textp {
 		fn := loader.Sym(s)
 		fi := d.ldr.FuncInfo(fn)
 		if !fi.Valid() {
@@ -1507,11 +1514,11 @@
 	return syms
 }
 
-func (d *dwctxt2) writeinfo(units []*sym.CompilationUnit, abbrevsym loader.Sym, pubNames, pubTypes *pubWriter2) dwarfSecInfo {
+func (d *dwctxt) writeinfo(units []*sym.CompilationUnit, abbrevsym loader.Sym, pubNames, pubTypes *pubWriter) dwarfSecInfo {
 
 	infosec := d.ldr.LookupOrCreateSym(".debug_info", 0)
 	disu := d.ldr.MakeSymbolUpdater(infosec)
-	disu.SetType(sym.SDWARFINFO)
+	disu.SetType(sym.SDWARFCUINFO)
 	d.ldr.SetAttrReachable(infosec, true)
 	syms := []loader.Sym{infosec}
 
@@ -1520,7 +1527,7 @@
 		s := d.dtolsym(compunit.Sym)
 		su := d.ldr.MakeSymbolUpdater(s)
 
-		if len(u.Textp2) == 0 && u.DWInfo.Child == nil {
+		if len(u.Textp) == 0 && u.DWInfo.Child == nil {
 			continue
 		}
 
@@ -1543,10 +1550,10 @@
 		dwarf.PutAttrs(d, ds, compunit.Abbrev, compunit.Attr)
 
 		cu := []loader.Sym{s}
-		cu = appendSyms(cu, u.AbsFnDIEs2)
-		cu = appendSyms(cu, u.FuncDIEs2)
-		if u.Consts2 != 0 {
-			cu = append(cu, loader.Sym(u.Consts2))
+		cu = appendSyms(cu, u.AbsFnDIEs)
+		cu = appendSyms(cu, u.FuncDIEs)
+		if u.Consts != 0 {
+			cu = append(cu, loader.Sym(u.Consts))
 		}
 		var cusize int64
 		for _, child := range cu {
@@ -1600,8 +1607,8 @@
  *  because we need die->offs and infoo/infosize;
  */
 
-type pubWriter2 struct {
-	d     *dwctxt2
+type pubWriter struct {
+	d     *dwctxt
 	s     loader.Sym
 	su    *loader.SymbolBuilder
 	sname string
@@ -1610,14 +1617,14 @@
 	culengthOff  int64
 }
 
-func newPubWriter2(d *dwctxt2, sname string) *pubWriter2 {
+func newPubWriter(d *dwctxt, sname string) *pubWriter {
 	s := d.ldr.LookupOrCreateSym(sname, 0)
 	u := d.ldr.MakeSymbolUpdater(s)
 	u.SetType(sym.SDWARFSECT)
-	return &pubWriter2{d: d, s: s, su: u, sname: sname}
+	return &pubWriter{d: d, s: s, su: u, sname: sname}
 }
 
-func (pw *pubWriter2) beginCompUnit(compunit *dwarf.DWDie) {
+func (pw *pubWriter) beginCompUnit(compunit *dwarf.DWDie) {
 	pw.sectionstart = pw.su.Size()
 
 	// Write .debug_pubnames/types	Header (sec 6.1.1)
@@ -1628,7 +1635,7 @@
 	pw.d.addDwarfAddrField(pw.su, uint64(0)) // debug_info_length, will be filled in later.
 }
 
-func (pw *pubWriter2) add(die *dwarf.DWDie, offset int64) {
+func (pw *pubWriter) add(die *dwarf.DWDie, offset int64) {
 	dwa := getattr(die, dwarf.DW_AT_name)
 	name := dwa.Data.(string)
 	if pw.d.dtolsym(die.Sym) == 0 {
@@ -1638,7 +1645,7 @@
 	pw.su.Addstring(name)
 }
 
-func (pw *pubWriter2) endCompUnit(compunit *dwarf.DWDie, culength uint32) {
+func (pw *pubWriter) endCompUnit(compunit *dwarf.DWDie, culength uint32) {
 	pw.d.addDwarfAddrField(pw.su, 0) // Null offset
 
 	// On AIX, save the current size of this compilation unit.
@@ -1668,7 +1675,7 @@
 	return die.Abbrev >= dwarf.DW_ABRV_NULLTYPE
 }
 
-func (d *dwctxt2) writegdbscript() dwarfSecInfo {
+func (d *dwctxt) writegdbscript() dwarfSecInfo {
 	// TODO (aix): make it available
 	if d.linkctxt.HeadType == objabi.Haix {
 		return dwarfSecInfo{}
@@ -1732,7 +1739,7 @@
 
 // mkBuiltinType populates the dwctxt2 sym lookup maps for the
 // newly created builtin type DIE 'typeDie'.
-func (d *dwctxt2) mkBuiltinType(ctxt *Link, abrv int, tname string) *dwarf.DWDie {
+func (d *dwctxt) mkBuiltinType(ctxt *Link, abrv int, tname string) *dwarf.DWDie {
 	// create type DIE
 	die := d.newdie(&dwtypes, abrv, tname, 0)
 
@@ -1749,6 +1756,76 @@
 	return die
 }
 
+// dwarfVisitFunction takes a function (text) symbol and processes the
+// subprogram DIE for the function and picks up any other DIEs
+// (absfns, types) that it references.
+func (d *dwctxt) dwarfVisitFunction(fnSym loader.Sym, unit *sym.CompilationUnit) {
+	// The DWARF subprogram DIE symbol is listed as an aux sym
+	// of the text (fcn) symbol, so ask the loader to retrieve it,
+	// as well as the associated range symbol.
+	infosym, _, rangesym, _ := d.ldr.GetFuncDwarfAuxSyms(fnSym)
+	if infosym == 0 {
+		return
+	}
+	d.ldr.SetAttrNotInSymbolTable(infosym, true)
+	d.ldr.SetAttrReachable(infosym, true)
+	unit.FuncDIEs = append(unit.FuncDIEs, sym.LoaderSym(infosym))
+	if rangesym != 0 {
+		rs := len(d.ldr.Data(rangesym))
+		d.ldr.SetAttrNotInSymbolTable(rangesym, true)
+		d.ldr.SetAttrReachable(rangesym, true)
+		if d.linkctxt.IsAIX() {
+			addDwsectCUSize(".debug_ranges", unit.Lib.Pkg, uint64(rs))
+		}
+		unit.RangeSyms = append(unit.RangeSyms, sym.LoaderSym(rangesym))
+	}
+
+	// Walk the relocations of the subprogram DIE symbol to discover
+	// references to abstract function DIEs, Go type DIES, and
+	// (via R_USETYPE relocs) types that were originally assigned to
+	// locals/params but were optimized away.
+	drelocs := d.ldr.Relocs(infosym)
+	for ri := 0; ri < drelocs.Count(); ri++ {
+		r := drelocs.At2(ri)
+		// Look for "use type" relocs.
+		if r.Type() == objabi.R_USETYPE {
+			d.defgotype(r.Sym())
+			continue
+		}
+		if r.Type() != objabi.R_DWARFSECREF {
+			continue
+		}
+
+		rsym := r.Sym()
+		rst := d.ldr.SymType(rsym)
+
+		// Look for abstract function references.
+		if rst == sym.SDWARFABSFCN {
+			if !d.ldr.AttrOnList(rsym) {
+				// abstract function
+				d.ldr.SetAttrOnList(rsym, true)
+				unit.AbsFnDIEs = append(unit.AbsFnDIEs, sym.LoaderSym(rsym))
+				d.importInfoSymbol(rsym)
+			}
+			continue
+		}
+
+		// Look for type references.
+		if rst != sym.SDWARFTYPE && rst != sym.Sxxx {
+			continue
+		}
+		if _, ok := d.rtmap[rsym]; ok {
+			// type already generated
+			continue
+		}
+
+		rsn := d.ldr.SymName(rsym)
+		tn := rsn[len(dwarf.InfoPrefix):]
+		ts := d.ldr.Lookup("type."+tn, 0)
+		d.defgotype(ts)
+	}
+}
+
 // dwarfGenerateDebugInfo generated debug info entries for all types,
 // variables and functions in the program.
 // Along with dwarfGenerateDebugSyms they are the two main entry points into
@@ -1761,7 +1838,7 @@
 		return
 	}
 
-	d := newdwctxt2(ctxt, true)
+	d := newdwctxt(ctxt, true)
 
 	if ctxt.HeadType == objabi.Haix {
 		// Initial map used to store package size for each DWARF section.
@@ -1822,8 +1899,8 @@
 		for _, unit := range lib.Units {
 			// We drop the constants into the first CU.
 			if consts != 0 {
-				unit.Consts2 = sym.LoaderSym(consts)
-				d.importInfoSymbol(ctxt, consts)
+				unit.Consts = sym.LoaderSym(consts)
+				d.importInfoSymbol(consts)
 				consts = 0
 			}
 			ctxt.compUnits = append(ctxt.compUnits, unit)
@@ -1833,7 +1910,11 @@
 				ctxt.runtimeCU = unit
 			}
 
-			unit.DWInfo = d.newdie(&dwroot, dwarf.DW_ABRV_COMPUNIT, unit.Lib.Pkg, 0)
+			cuabrv := dwarf.DW_ABRV_COMPUNIT
+			if len(unit.Textp) == 0 {
+				cuabrv = dwarf.DW_ABRV_COMPUNIT_TEXTLESS
+			}
+			unit.DWInfo = d.newdie(&dwroot, cuabrv, unit.Lib.Pkg, 0)
 			newattr(unit.DWInfo, dwarf.DW_AT_language, dwarf.DW_CLS_CONSTANT, int64(dwarf.DW_LANG_Go), 0)
 			// OS X linker requires compilation dir or absolute path in comp unit name to output debug info.
 			compDir := getCompilationDir()
@@ -1869,60 +1950,12 @@
 			}
 			newattr(unit.DWInfo, dwarf.DW_AT_go_package_name, dwarf.DW_CLS_STRING, int64(len(pkgname)), pkgname)
 
-			if len(unit.Textp2) == 0 {
-				unit.DWInfo.Abbrev = dwarf.DW_ABRV_COMPUNIT_TEXTLESS
-			}
-
-			// Scan all functions in this compilation unit, create DIEs for all
-			// referenced types, create the file table for debug_line, find all
-			// referenced abstract functions.
-			// Collect all debug_range symbols in unit.rangeSyms
-			for _, s := range unit.Textp2 { // textp2 has been dead-code-eliminated already.
-				fnSym := loader.Sym(s)
-				infosym, _, rangesym, _ := d.ldr.GetFuncDwarfAuxSyms(fnSym)
-				if infosym == 0 {
-					continue
-				}
-				d.ldr.SetAttrNotInSymbolTable(infosym, true)
-				d.ldr.SetAttrReachable(infosym, true)
-
-				unit.FuncDIEs2 = append(unit.FuncDIEs2, sym.LoaderSym(infosym))
-				if rangesym != 0 {
-					rs := len(d.ldr.Data(rangesym))
-					d.ldr.SetAttrNotInSymbolTable(rangesym, true)
-					d.ldr.SetAttrReachable(rangesym, true)
-					if ctxt.HeadType == objabi.Haix {
-						addDwsectCUSize(".debug_ranges", unit.Lib.Pkg, uint64(rs))
-					}
-					unit.RangeSyms2 = append(unit.RangeSyms2, sym.LoaderSym(rangesym))
-				}
-
-				drelocs := d.ldr.Relocs(infosym)
-				for ri := 0; ri < drelocs.Count(); ri++ {
-					r := drelocs.At2(ri)
-					if r.Type() == objabi.R_DWARFSECREF {
-						rsym := r.Sym()
-						rsn := d.ldr.SymName(rsym)
-						if len(rsn) == 0 {
-							continue
-						}
-						// NB: there should be a better way to do this that doesn't involve materializing the symbol name and doing string prefix+suffix checks.
-						if strings.HasPrefix(rsn, dwarf.InfoPrefix) && strings.HasSuffix(rsn, dwarf.AbstractFuncSuffix) && !d.ldr.AttrOnList(rsym) {
-							// abstract function
-							d.ldr.SetAttrOnList(rsym, true)
-							unit.AbsFnDIEs2 = append(unit.AbsFnDIEs2, sym.LoaderSym(rsym))
-							d.importInfoSymbol(ctxt, rsym)
-							continue
-						}
-						if _, ok := d.rtmap[rsym]; ok {
-							// type already generated
-							continue
-						}
-						tn := rsn[len(dwarf.InfoPrefix):]
-						ts := d.ldr.Lookup("type."+tn, 0)
-						d.defgotype(ts)
-					}
-				}
+			// Scan all functions in this compilation unit, create
+			// DIEs for all referenced types, find all referenced
+			// abstract functions, visit range symbols. Note that
+			// Textp has been dead-code-eliminated already.
+			for _, s := range unit.Textp {
+				d.dwarfVisitFunction(loader.Sym(s), unit)
 			}
 		}
 	}
@@ -1971,26 +2004,6 @@
 		d.dwarfDefineGlobal(ctxt, idx, sn, sv, gt)
 	}
 
-	// Create DIEs for variable types indirectly referenced by function
-	// autos (which may not appear directly as param/var DIEs).
-	for _, lib := range ctxt.Library {
-		for _, unit := range lib.Units {
-			lists := [][]sym.LoaderSym{unit.AbsFnDIEs2, unit.FuncDIEs2}
-			for _, list := range lists {
-				for _, s := range list {
-					symIdx := loader.Sym(s)
-					relocs := d.ldr.Relocs(symIdx)
-					for i := 0; i < relocs.Count(); i++ {
-						r := relocs.At2(i)
-						if r.Type() == objabi.R_USETYPE {
-							d.defgotype(r.Sym())
-						}
-					}
-				}
-			}
-		}
-	}
-
 	d.synthesizestringtypes(ctxt, dwtypes.Child)
 	d.synthesizeslicetypes(ctxt, dwtypes.Child)
 	d.synthesizemaptypes(ctxt, dwtypes.Child)
@@ -2009,7 +2022,7 @@
 	if !dwarfEnabled(ctxt) {
 		return
 	}
-	d := &dwctxt2{
+	d := &dwctxt{
 		linkctxt: ctxt,
 		ldr:      ctxt.loader,
 		arch:     ctxt.Arch,
@@ -2017,9 +2030,9 @@
 	d.dwarfGenerateDebugSyms()
 }
 
-func (d *dwctxt2) dwarfGenerateDebugSyms() {
+func (d *dwctxt) dwarfGenerateDebugSyms() {
 	abbrevSec := d.writeabbrev()
-	dwarfp2 = append(dwarfp2, abbrevSec)
+	dwarfp = append(dwarfp, abbrevSec)
 
 	d.calcCompUnitRanges()
 	sort.Sort(compilationUnitByStartPC(d.linkctxt.compUnits))
@@ -2029,7 +2042,7 @@
 	dlu := d.ldr.MakeSymbolUpdater(debugLine)
 	dlu.SetType(sym.SDWARFSECT)
 	d.ldr.SetAttrReachable(debugLine, true)
-	dwarfp2 = append(dwarfp2, dwarfSecInfo{syms: []loader.Sym{debugLine}})
+	dwarfp = append(dwarfp, dwarfSecInfo{syms: []loader.Sym{debugLine}})
 
 	debugRanges := d.ldr.LookupOrCreateSym(".debug_ranges", 0)
 	dru := d.ldr.MakeSymbolUpdater(debugRanges)
@@ -2043,7 +2056,7 @@
 			continue
 		}
 		d.writelines(u, debugLine)
-		base := loader.Sym(u.Textp2[0])
+		base := loader.Sym(u.Textp[0])
 		d.writepcranges(u, base, u.PCs, debugRanges)
 	}
 
@@ -2053,39 +2066,39 @@
 	reversetree(&dwtypes.Child)
 	movetomodule(d.linkctxt, &dwtypes)
 
-	pubNames := newPubWriter2(d, ".debug_pubnames")
-	pubTypes := newPubWriter2(d, ".debug_pubtypes")
+	pubNames := newPubWriter(d, ".debug_pubnames")
+	pubTypes := newPubWriter(d, ".debug_pubtypes")
 
 	infoSec := d.writeinfo(d.linkctxt.compUnits, abbrevSec.secSym(), pubNames, pubTypes)
 
 	framesSec := d.writeframes()
-	dwarfp2 = append(dwarfp2, framesSec)
-	dwarfp2 = append(dwarfp2, dwarfSecInfo{syms: []loader.Sym{pubNames.s}})
-	dwarfp2 = append(dwarfp2, dwarfSecInfo{syms: []loader.Sym{pubTypes.s}})
+	dwarfp = append(dwarfp, framesSec)
+	dwarfp = append(dwarfp, dwarfSecInfo{syms: []loader.Sym{pubNames.s}})
+	dwarfp = append(dwarfp, dwarfSecInfo{syms: []loader.Sym{pubTypes.s}})
 	gdbScriptSec := d.writegdbscript()
 	if gdbScriptSec.secSym() != 0 {
-		dwarfp2 = append(dwarfp2, gdbScriptSec)
+		dwarfp = append(dwarfp, gdbScriptSec)
 	}
-	dwarfp2 = append(dwarfp2, infoSec)
+	dwarfp = append(dwarfp, infoSec)
 	locSec := d.collectlocs(d.linkctxt.compUnits)
 	if locSec.secSym() != 0 {
-		dwarfp2 = append(dwarfp2, locSec)
+		dwarfp = append(dwarfp, locSec)
 	}
 
 	rsyms := []loader.Sym{debugRanges}
 	for _, unit := range d.linkctxt.compUnits {
-		for _, s := range unit.RangeSyms2 {
+		for _, s := range unit.RangeSyms {
 			rsyms = append(rsyms, loader.Sym(s))
 		}
 	}
-	dwarfp2 = append(dwarfp2, dwarfSecInfo{syms: rsyms})
+	dwarfp = append(dwarfp, dwarfSecInfo{syms: rsyms})
 }
 
-func (d *dwctxt2) collectlocs(units []*sym.CompilationUnit) dwarfSecInfo {
+func (d *dwctxt) collectlocs(units []*sym.CompilationUnit) dwarfSecInfo {
 	empty := true
 	syms := []loader.Sym{}
 	for _, u := range units {
-		for _, fn := range u.FuncDIEs2 {
+		for _, fn := range u.FuncDIEs {
 			relocs := d.ldr.Relocs(loader.Sym(fn))
 			for i := 0; i < relocs.Count(); i++ {
 				reloc := relocs.At2(i)
@@ -2117,31 +2130,11 @@
 	return dwarfSecInfo{syms: append([]loader.Sym{locsym}, syms...)}
 }
 
-/*
- *  Elf.
- */
-func (d *dwctxt2) dwarfaddshstrings(ctxt *Link, shstrtab loader.Sym) {
-	panic("not yet implemented")
-}
-
-// Add section symbols for DWARF debug info.  This is called before
-// dwarfaddelfheaders.
-func (d *dwctxt2) dwarfaddelfsectionsyms(ctxt *Link) {
-	panic("not yet implemented")
-}
-
-// dwarfcompress compresses the DWARF sections. Relocations are applied
-// on the fly. After this, dwarfp will contain a different (new) set of
-// symbols, and sections may have been replaced.
-func (d *dwctxt2) dwarfcompress(ctxt *Link) {
-	panic("not yet implemented")
-}
-
 // getPkgFromCUSym returns the package name for the compilation unit
 // represented by s.
 // The prefix dwarf.InfoPrefix+".pkg." needs to be removed in order to get
 // the package name.
-func (d *dwctxt2) getPkgFromCUSym(s loader.Sym) string {
+func (d *dwctxt) getPkgFromCUSym(s loader.Sym) string {
 	return strings.TrimPrefix(d.ldr.SymName(s), dwarf.InfoPrefix+".pkg.")
 }
 
@@ -2164,3 +2157,19 @@
 func addDwsectCUSize(sname string, pkgname string, size uint64) {
 	dwsectCUSize[sname+"."+pkgname] += size
 }
+
+func dwarfaddelfsectionsyms(ctxt *Link) {
+	if *FlagW { // disable dwarf
+		return
+	}
+	if ctxt.LinkMode != LinkExternal {
+		return
+	}
+
+	ldr := ctxt.loader
+	for _, si := range dwarfp {
+		s := si.secSym()
+		sect := ldr.SymSect(si.secSym())
+		putelfsectionsym(ctxt, ctxt.Out, s, sect.Elfsect.(*ElfShdr).shnum)
+	}
+}
diff --git a/src/cmd/link/internal/ld/dwarf2.go b/src/cmd/link/internal/ld/dwarf2.go
index 79abccf..0c1a0ca 100644
--- a/src/cmd/link/internal/ld/dwarf2.go
+++ b/src/cmd/link/internal/ld/dwarf2.go
@@ -24,28 +24,6 @@
 	return ctxt.HeadType == objabi.Haix
 }
 
-// dwarfSecInfo2 is a replica of the dwarfSecInfo struct but with
-// *sym.Symbol content instead of loader.Sym content.
-type dwarfSecInfo2 struct {
-	syms []*sym.Symbol
-}
-
-func (dsi *dwarfSecInfo2) secSym() *sym.Symbol {
-	if len(dsi.syms) == 0 {
-		return nil
-	}
-	return dsi.syms[0]
-}
-
-func (dsi *dwarfSecInfo2) subSyms() []*sym.Symbol {
-	if len(dsi.syms) == 0 {
-		return []*sym.Symbol{}
-	}
-	return dsi.syms[1:]
-}
-
-var dwarfp []dwarfSecInfo2
-
 /*
  *  Elf.
  */
@@ -65,34 +43,6 @@
 	}
 }
 
-// Add section symbols for DWARF debug info.  This is called before
-// dwarfaddelfheaders.
-func dwarfaddelfsectionsyms(ctxt *Link) {
-	if *FlagW { // disable dwarf
-		return
-	}
-	if ctxt.LinkMode != LinkExternal {
-		return
-	}
-
-	s := ctxt.Syms.Lookup(".debug_info", 0)
-	putelfsectionsym(ctxt, ctxt.Out, s, s.Sect.Elfsect.(*ElfShdr).shnum)
-	s = ctxt.Syms.Lookup(".debug_abbrev", 0)
-	putelfsectionsym(ctxt, ctxt.Out, s, s.Sect.Elfsect.(*ElfShdr).shnum)
-	s = ctxt.Syms.Lookup(".debug_line", 0)
-	putelfsectionsym(ctxt, ctxt.Out, s, s.Sect.Elfsect.(*ElfShdr).shnum)
-	s = ctxt.Syms.Lookup(".debug_frame", 0)
-	putelfsectionsym(ctxt, ctxt.Out, s, s.Sect.Elfsect.(*ElfShdr).shnum)
-	s = ctxt.Syms.Lookup(".debug_loc", 0)
-	if s.Sect != nil {
-		putelfsectionsym(ctxt, ctxt.Out, s, s.Sect.Elfsect.(*ElfShdr).shnum)
-	}
-	s = ctxt.Syms.Lookup(".debug_ranges", 0)
-	if s.Sect != nil {
-		putelfsectionsym(ctxt, ctxt.Out, s, s.Sect.Elfsect.(*ElfShdr).shnum)
-	}
-}
-
 // dwarfcompress compresses the DWARF sections. Relocations are applied
 // on the fly. After this, dwarfp will contain a different (new) set of
 // symbols, and sections may have been replaced.
@@ -111,10 +61,10 @@
 
 	var compressedCount int
 	resChannel := make(chan compressedSect)
-	for i := range dwarfp2 {
+	for i := range dwarfp {
 		go func(resIndex int, syms []loader.Sym) {
 			resChannel <- compressedSect{resIndex, compressSyms(ctxt, syms), syms}
-		}(compressedCount, dwarfp2[i].syms)
+		}(compressedCount, dwarfp[i].syms)
 		compressedCount++
 	}
 	res := make([]compressedSect, compressedCount)
@@ -153,14 +103,14 @@
 			}
 		}
 	}
-	dwarfp2 = newDwarfp
+	dwarfp = 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 dwarfp2 {
+	for _, si := range dwarfp {
 		for _, s := range si.syms {
 			ldr.SetSymValue(s, int64(pos))
 			sect := ldr.SymSect(s)
@@ -187,11 +137,11 @@
 
 func (v compilationUnitByStartPC) Less(i, j int) bool {
 	switch {
-	case len(v[i].Textp2) == 0 && len(v[j].Textp2) == 0:
+	case len(v[i].Textp) == 0 && len(v[j].Textp) == 0:
 		return v[i].Lib.Pkg < v[j].Lib.Pkg
-	case len(v[i].Textp2) != 0 && len(v[j].Textp2) == 0:
+	case len(v[i].Textp) != 0 && len(v[j].Textp) == 0:
 		return true
-	case len(v[i].Textp2) == 0 && len(v[j].Textp2) != 0:
+	case len(v[i].Textp) == 0 && len(v[j].Textp) != 0:
 		return false
 	default:
 		return v[i].PCs[0].Start < v[j].PCs[0].Start
diff --git a/src/cmd/link/internal/ld/elf.go b/src/cmd/link/internal/ld/elf.go
index 78298be..b100d07 100644
--- a/src/cmd/link/internal/ld/elf.go
+++ b/src/cmd/link/internal/ld/elf.go
@@ -12,7 +12,6 @@
 	"crypto/sha1"
 	"encoding/binary"
 	"encoding/hex"
-	"io"
 	"path/filepath"
 	"sort"
 	"strings"
@@ -628,7 +627,7 @@
 	return uint32(ehdr.shnum) * ELF32SHDRSIZE
 }
 
-func elfsetstring2(ctxt *Link, s loader.Sym, str string, off int) {
+func elfsetstring(ctxt *Link, s loader.Sym, str string, off int) {
 	if nelfstr >= len(elfstr) {
 		ctxt.Errorf(s, "too many elf strings")
 		errorexit()
@@ -743,7 +742,11 @@
 	return h
 }
 
-func elfWriteDynEnt(arch *sys.Arch, s *sym.Symbol, tag int, val uint64) {
+func elfWriteDynEntSym(ctxt *Link, s *loader.SymbolBuilder, tag int, t loader.Sym) {
+	Elfwritedynentsymplus(ctxt, s, tag, t, 0)
+}
+
+func Elfwritedynent(arch *sys.Arch, s *loader.SymbolBuilder, tag int, val uint64) {
 	if elf64 {
 		s.AddUint64(arch, uint64(tag))
 		s.AddUint64(arch, val)
@@ -753,44 +756,11 @@
 	}
 }
 
-func elfWriteDynEntSym2(ctxt *Link, s *loader.SymbolBuilder, tag int, t loader.Sym) {
-	Elfwritedynentsymplus2(ctxt, s, tag, t, 0)
+func elfwritedynentsym(ctxt *Link, s *loader.SymbolBuilder, tag int, t loader.Sym) {
+	Elfwritedynentsymplus(ctxt, s, tag, t, 0)
 }
 
-func Elfwritedynentsymplus(arch *sys.Arch, s *sym.Symbol, tag int, t *sym.Symbol, add int64) {
-	if elf64 {
-		s.AddUint64(arch, uint64(tag))
-	} else {
-		s.AddUint32(arch, uint32(tag))
-	}
-	s.AddAddrPlus(arch, t, add)
-}
-
-func elfWriteDynEntSymSize(arch *sys.Arch, s *sym.Symbol, tag int, t *sym.Symbol) {
-	if elf64 {
-		s.AddUint64(arch, uint64(tag))
-	} else {
-		s.AddUint32(arch, uint32(tag))
-	}
-	s.AddSize(arch, t)
-}
-
-// temporary
-func Elfwritedynent2(arch *sys.Arch, s *loader.SymbolBuilder, tag int, val uint64) {
-	if elf64 {
-		s.AddUint64(arch, uint64(tag))
-		s.AddUint64(arch, val)
-	} else {
-		s.AddUint32(arch, uint32(tag))
-		s.AddUint32(arch, uint32(val))
-	}
-}
-
-func elfwritedynentsym2(ctxt *Link, s *loader.SymbolBuilder, tag int, t loader.Sym) {
-	Elfwritedynentsymplus2(ctxt, s, tag, t, 0)
-}
-
-func Elfwritedynentsymplus2(ctxt *Link, s *loader.SymbolBuilder, tag int, t loader.Sym, add int64) {
+func Elfwritedynentsymplus(ctxt *Link, s *loader.SymbolBuilder, tag int, t loader.Sym, add int64) {
 	if elf64 {
 		s.AddUint64(ctxt.Arch, uint64(tag))
 	} else {
@@ -799,7 +769,7 @@
 	s.AddAddrPlus(ctxt.Arch, t, add)
 }
 
-func elfwritedynentsymsize2(ctxt *Link, s *loader.SymbolBuilder, tag int, t loader.Sym) {
+func elfwritedynentsymsize(ctxt *Link, s *loader.SymbolBuilder, tag int, t loader.Sym) {
 	if elf64 {
 		s.AddUint64(ctxt.Arch, uint64(tag))
 	} else {
@@ -1057,7 +1027,7 @@
 	return aux
 }
 
-func elfdynhash2(ctxt *Link) {
+func elfdynhash(ctxt *Link) {
 	if !ctxt.IsELF {
 		return
 	}
@@ -1175,23 +1145,23 @@
 	s = ldr.CreateSymForUpdate(".dynamic", 0)
 	elfverneed = nfile
 	if elfverneed != 0 {
-		elfWriteDynEntSym2(ctxt, s, DT_VERNEED, gnuVersionR.Sym())
-		Elfwritedynent2(ctxt.Arch, s, DT_VERNEEDNUM, uint64(nfile))
-		elfWriteDynEntSym2(ctxt, s, DT_VERSYM, gnuVersion.Sym())
+		elfWriteDynEntSym(ctxt, s, DT_VERNEED, gnuVersionR.Sym())
+		Elfwritedynent(ctxt.Arch, s, DT_VERNEEDNUM, uint64(nfile))
+		elfWriteDynEntSym(ctxt, s, DT_VERSYM, gnuVersion.Sym())
 	}
 
 	sy := ldr.CreateSymForUpdate(elfRelType+".plt", 0)
 	if sy.Size() > 0 {
 		if elfRelType == ".rela" {
-			Elfwritedynent2(ctxt.Arch, s, DT_PLTREL, DT_RELA)
+			Elfwritedynent(ctxt.Arch, s, DT_PLTREL, DT_RELA)
 		} else {
-			Elfwritedynent2(ctxt.Arch, s, DT_PLTREL, DT_REL)
+			Elfwritedynent(ctxt.Arch, s, DT_PLTREL, DT_REL)
 		}
-		elfwritedynentsymsize2(ctxt, s, DT_PLTRELSZ, sy.Sym())
-		elfWriteDynEntSym2(ctxt, s, DT_JMPREL, sy.Sym())
+		elfwritedynentsymsize(ctxt, s, DT_PLTRELSZ, sy.Sym())
+		elfWriteDynEntSym(ctxt, s, DT_JMPREL, sy.Sym())
 	}
 
-	Elfwritedynent2(ctxt.Arch, s, DT_NULL, 0)
+	Elfwritedynent(ctxt.Arch, s, DT_NULL, 0)
 }
 
 func elfphload(seg *sym.Segment) *ElfPhdr {
@@ -1373,12 +1343,7 @@
 	return sh
 }
 
-func elfrelocsect(ctxt *Link, sect *sym.Section, syms []*sym.Symbol) {
-	if !ctxt.IsAMD64() {
-		elfrelocsect2(ctxt, sect, syms)
-		return
-	}
-
+func elfrelocsect(ctxt *Link, sect *sym.Section, syms []loader.Sym) {
 	// If main section is SHT_NOBITS, nothing to relocate.
 	// Also nothing to relocate in .shstrtab.
 	if sect.Vaddr >= sect.Seg.Vaddr+sect.Seg.Filelen {
@@ -1388,43 +1353,43 @@
 		return
 	}
 
+	ldr := ctxt.loader
 	sect.Reloff = uint64(ctxt.Out.Offset())
 	for i, s := range syms {
-		if !s.Attr.Reachable() {
-			continue
+		if !ldr.AttrReachable(s) {
+			panic("should never happen")
 		}
-		if uint64(s.Value) >= sect.Vaddr {
+		if uint64(ldr.SymValue(s)) >= sect.Vaddr {
 			syms = syms[i:]
 			break
 		}
 	}
 
-	ldr := ctxt.loader
 	eaddr := int32(sect.Vaddr + sect.Length)
 	for _, s := range syms {
-		if !s.Attr.Reachable() {
+		if !ldr.AttrReachable(s) {
 			continue
 		}
-		if s.Value >= int64(eaddr) {
+		if ldr.SymValue(s) >= int64(eaddr) {
 			break
 		}
-		i := loader.Sym(s.SymIdx)
-		relocs := ldr.ExtRelocs(i)
+
+		relocs := ldr.ExtRelocs(s)
 		for ri := 0; ri < relocs.Count(); ri++ {
 			r := relocs.At(ri)
 			if r.Xsym == 0 {
-				Errorf(s, "missing xsym in relocation %v", ldr.SymName(r.Sym()))
+				ldr.Errorf(s, "missing xsym in relocation")
 				continue
 			}
-			esr := ElfSymForReloc(ctxt, ldr.Syms[r.Xsym])
+			esr := ElfSymForReloc(ctxt, r.Xsym)
 			if esr == 0 {
-				Errorf(s, "reloc %d (%s) to non-elf symbol %s (outer=%s) %d (%s)", r.Type(), sym.RelocName(ctxt.Arch, r.Type()), ldr.Syms[r.Sym()].Name, ldr.Syms[r.Xsym].Name, ldr.Syms[r.Sym()].Type, ldr.Syms[r.Sym()].Type)
+				ldr.Errorf(s, "reloc %d (%s) to non-elf symbol %s (outer=%s) %d (%s)", r.Type(), sym.RelocName(ctxt.Arch, r.Type()), ldr.SymName(r.Sym()), ldr.SymName(r.Xsym), ldr.SymType(r.Sym()), ldr.SymType(r.Sym()).String())
 			}
 			if !ldr.AttrReachable(r.Xsym) {
-				Errorf(s, "unreachable reloc %d (%s) target %v", r.Type(), sym.RelocName(ctxt.Arch, r.Type()), ldr.Syms[r.Xsym].Name)
+				ldr.Errorf(s, "unreachable reloc %d (%s) target %v", r.Type(), sym.RelocName(ctxt.Arch, r.Type()), ldr.SymName(r.Xsym))
 			}
-			if !thearch.Elfreloc2(ctxt, ldr, i, r, int64(uint64(s.Value+int64(r.Off()))-sect.Vaddr)) {
-				Errorf(s, "unsupported obj reloc %d (%s)/%d to %s", r.Type(), sym.RelocName(ctxt.Arch, r.Type()), r.Siz(), ldr.Syms[r.Sym()].Name)
+			if !thearch.Elfreloc1(ctxt, ldr, s, r, int64(uint64(ldr.SymValue(s)+int64(r.Off()))-sect.Vaddr)) {
+				ldr.Errorf(s, "unsupported obj reloc %d (%s)/%d to %s", r.Type, sym.RelocName(ctxt.Arch, r.Type()), r.Siz(), ldr.SymName(r.Sym()))
 			}
 		}
 	}
@@ -1432,7 +1397,8 @@
 	sect.Rellen = uint64(ctxt.Out.Offset()) - sect.Reloff
 }
 
-func Elfemitreloc(ctxt *Link) {
+func elfEmitReloc(ctxt *Link) {
+
 	for ctxt.Out.Offset()&7 != 0 {
 		ctxt.Out.Write8(0)
 	}
@@ -1457,8 +1423,8 @@
 	for i := 0; i < len(Segdwarf.Sections); i++ {
 		sect := Segdwarf.Sections[i]
 		si := dwarfp[i]
-		if si.secSym() != sect.Sym ||
-			si.secSym().Sect != sect {
+		if si.secSym() != loader.Sym(sect.Sym) ||
+			ctxt.loader.SymSect(si.secSym()) != sect {
 			panic("inconsistency between dwarfp and Segdwarf")
 		}
 		elfrelocsect(ctxt, sect, si.syms)
@@ -1689,47 +1655,47 @@
 		/*
 		 * .dynamic table
 		 */
-		elfwritedynentsym2(ctxt, dynamic, DT_HASH, hash.Sym())
+		elfwritedynentsym(ctxt, dynamic, DT_HASH, hash.Sym())
 
-		elfwritedynentsym2(ctxt, dynamic, DT_SYMTAB, dynsym.Sym())
+		elfwritedynentsym(ctxt, dynamic, DT_SYMTAB, dynsym.Sym())
 		if elf64 {
-			Elfwritedynent2(ctxt.Arch, dynamic, DT_SYMENT, ELF64SYMSIZE)
+			Elfwritedynent(ctxt.Arch, dynamic, DT_SYMENT, ELF64SYMSIZE)
 		} else {
-			Elfwritedynent2(ctxt.Arch, dynamic, DT_SYMENT, ELF32SYMSIZE)
+			Elfwritedynent(ctxt.Arch, dynamic, DT_SYMENT, ELF32SYMSIZE)
 		}
-		elfwritedynentsym2(ctxt, dynamic, DT_STRTAB, dynstr.Sym())
-		elfwritedynentsymsize2(ctxt, dynamic, DT_STRSZ, dynstr.Sym())
+		elfwritedynentsym(ctxt, dynamic, DT_STRTAB, dynstr.Sym())
+		elfwritedynentsymsize(ctxt, dynamic, DT_STRSZ, dynstr.Sym())
 		if elfRelType == ".rela" {
 			rela := ldr.LookupOrCreateSym(".rela", 0)
-			elfwritedynentsym2(ctxt, dynamic, DT_RELA, rela)
-			elfwritedynentsymsize2(ctxt, dynamic, DT_RELASZ, rela)
-			Elfwritedynent2(ctxt.Arch, dynamic, DT_RELAENT, ELF64RELASIZE)
+			elfwritedynentsym(ctxt, dynamic, DT_RELA, rela)
+			elfwritedynentsymsize(ctxt, dynamic, DT_RELASZ, rela)
+			Elfwritedynent(ctxt.Arch, dynamic, DT_RELAENT, ELF64RELASIZE)
 		} else {
 			rel := ldr.LookupOrCreateSym(".rel", 0)
-			elfwritedynentsym2(ctxt, dynamic, DT_REL, rel)
-			elfwritedynentsymsize2(ctxt, dynamic, DT_RELSZ, rel)
-			Elfwritedynent2(ctxt.Arch, dynamic, DT_RELENT, ELF32RELSIZE)
+			elfwritedynentsym(ctxt, dynamic, DT_REL, rel)
+			elfwritedynentsymsize(ctxt, dynamic, DT_RELSZ, rel)
+			Elfwritedynent(ctxt.Arch, dynamic, DT_RELENT, ELF32RELSIZE)
 		}
 
 		if rpath.val != "" {
-			Elfwritedynent2(ctxt.Arch, dynamic, DT_RUNPATH, uint64(dynstr.Addstring(rpath.val)))
+			Elfwritedynent(ctxt.Arch, dynamic, DT_RUNPATH, uint64(dynstr.Addstring(rpath.val)))
 		}
 
 		if ctxt.IsPPC64() {
-			elfwritedynentsym2(ctxt, dynamic, DT_PLTGOT, plt.Sym())
+			elfwritedynentsym(ctxt, dynamic, DT_PLTGOT, plt.Sym())
 		} else {
-			elfwritedynentsym2(ctxt, dynamic, DT_PLTGOT, gotplt.Sym())
+			elfwritedynentsym(ctxt, dynamic, DT_PLTGOT, gotplt.Sym())
 		}
 
 		if ctxt.IsPPC64() {
-			Elfwritedynent2(ctxt.Arch, dynamic, DT_PPC64_OPT, 0)
+			Elfwritedynent(ctxt.Arch, dynamic, DT_PPC64_OPT, 0)
 		}
 
 		// Solaris dynamic linker can't handle an empty .rela.plt if
 		// DT_JMPREL is emitted so we have to defer generation of DT_PLTREL,
 		// DT_PLTRELSZ, and DT_JMPREL dynamic entries until after we know the
 		// size of .rel(a).plt section.
-		Elfwritedynent2(ctxt.Arch, dynamic, DT_DEBUG, 0)
+		Elfwritedynent(ctxt.Arch, dynamic, DT_DEBUG, 0)
 	}
 
 	if ctxt.IsShared() {
@@ -1746,7 +1712,7 @@
 		sort.Sort(byPkg(ctxt.Library))
 		h := sha1.New()
 		for _, l := range ctxt.Library {
-			io.WriteString(h, l.Hash)
+			h.Write(l.Fingerprint[:])
 		}
 		addgonote(ctxt, ".note.go.abihash", ELF_NOTE_GOABIHASH_TAG, h.Sum([]byte{}))
 		addgonote(ctxt, ".note.go.pkg-list", ELF_NOTE_GOPKGLIST_TAG, pkglistfornote)
@@ -1763,13 +1729,16 @@
 }
 
 // Do not write DT_NULL.  elfdynhash will finish it.
-func shsym(sh *ElfShdr, s *sym.Symbol) {
-	addr := Symaddr(s)
+func shsym(sh *ElfShdr, ldr *loader.Loader, s loader.Sym) {
+	if s == 0 {
+		panic("bad symbol in shsym2")
+	}
+	addr := ldr.SymValue(s)
 	if sh.flags&SHF_ALLOC != 0 {
 		sh.addr = uint64(addr)
 	}
-	sh.off = uint64(datoff(s, addr))
-	sh.size = uint64(s.Size)
+	sh.off = uint64(datoff(ldr, s, addr))
+	sh.size = uint64(ldr.SymSize(s))
 }
 
 func phsh(ph *ElfPhdr, sh *ElfShdr) {
@@ -1810,7 +1779,21 @@
 	}
 }
 
-func Asmbelf(ctxt *Link, symo int64) {
+func asmbElf(ctxt *Link) {
+	var symo int64
+	if !*FlagS {
+		symo = int64(Segdwarf.Fileoff + Segdwarf.Filelen)
+		symo = Rnd(symo, int64(*FlagRound))
+		ctxt.Out.SeekSet(symo)
+		asmElfSym(ctxt)
+		ctxt.Out.Write(Elfstrdat)
+		if ctxt.IsExternal() {
+			elfEmitReloc(ctxt)
+		}
+	}
+	ctxt.Out.SeekSet(0)
+
+	ldr := ctxt.loader
 	eh := getElfEhdr()
 	switch ctxt.Arch.Family {
 	default:
@@ -2029,22 +2012,22 @@
 		sh.link = uint32(elfshname(".dynstr").shnum)
 
 		// sh.info is the index of first non-local symbol (number of local symbols)
-		s := ctxt.Syms.Lookup(".dynsym", 0)
+		s := ldr.Lookup(".dynsym", 0)
 		i := uint32(0)
-		for sub := s; sub != nil; sub = symSub(ctxt, sub) {
+		for sub := s; sub != 0; sub = ldr.SubSym(sub) {
 			i++
-			if !sub.Attr.Local() {
+			if !ldr.AttrLocal(sub) {
 				break
 			}
 		}
 		sh.info = i
-		shsym(sh, s)
+		shsym(sh, ldr, s)
 
 		sh = elfshname(".dynstr")
 		sh.type_ = SHT_STRTAB
 		sh.flags = SHF_ALLOC
 		sh.addralign = 1
-		shsym(sh, ctxt.Syms.Lookup(".dynstr", 0))
+		shsym(sh, ldr, ldr.Lookup(".dynstr", 0))
 
 		if elfverneed != 0 {
 			sh := elfshname(".gnu.version")
@@ -2053,7 +2036,7 @@
 			sh.addralign = 2
 			sh.link = uint32(elfshname(".dynsym").shnum)
 			sh.entsize = 2
-			shsym(sh, ctxt.Syms.Lookup(".gnu.version", 0))
+			shsym(sh, ldr, ldr.Lookup(".gnu.version", 0))
 
 			sh = elfshname(".gnu.version_r")
 			sh.type_ = SHT_GNU_VERNEED
@@ -2061,7 +2044,7 @@
 			sh.addralign = uint64(ctxt.Arch.RegSize)
 			sh.info = uint32(elfverneed)
 			sh.link = uint32(elfshname(".dynstr").shnum)
-			shsym(sh, ctxt.Syms.Lookup(".gnu.version_r", 0))
+			shsym(sh, ldr, ldr.Lookup(".gnu.version_r", 0))
 		}
 
 		if elfRelType == ".rela" {
@@ -2072,7 +2055,7 @@
 			sh.addralign = uint64(ctxt.Arch.RegSize)
 			sh.link = uint32(elfshname(".dynsym").shnum)
 			sh.info = uint32(elfshname(".plt").shnum)
-			shsym(sh, ctxt.Syms.Lookup(".rela.plt", 0))
+			shsym(sh, ldr, ldr.Lookup(".rela.plt", 0))
 
 			sh = elfshname(".rela")
 			sh.type_ = SHT_RELA
@@ -2080,7 +2063,7 @@
 			sh.entsize = ELF64RELASIZE
 			sh.addralign = 8
 			sh.link = uint32(elfshname(".dynsym").shnum)
-			shsym(sh, ctxt.Syms.Lookup(".rela", 0))
+			shsym(sh, ldr, ldr.Lookup(".rela", 0))
 		} else {
 			sh := elfshname(".rel.plt")
 			sh.type_ = SHT_REL
@@ -2088,7 +2071,7 @@
 			sh.entsize = ELF32RELSIZE
 			sh.addralign = 4
 			sh.link = uint32(elfshname(".dynsym").shnum)
-			shsym(sh, ctxt.Syms.Lookup(".rel.plt", 0))
+			shsym(sh, ldr, ldr.Lookup(".rel.plt", 0))
 
 			sh = elfshname(".rel")
 			sh.type_ = SHT_REL
@@ -2096,7 +2079,7 @@
 			sh.entsize = ELF32RELSIZE
 			sh.addralign = 4
 			sh.link = uint32(elfshname(".dynsym").shnum)
-			shsym(sh, ctxt.Syms.Lookup(".rel", 0))
+			shsym(sh, ldr, ldr.Lookup(".rel", 0))
 		}
 
 		if eh.machine == EM_PPC64 {
@@ -2104,7 +2087,7 @@
 			sh.type_ = SHT_PROGBITS
 			sh.flags = SHF_ALLOC + SHF_EXECINSTR
 			sh.addralign = 4
-			shsym(sh, ctxt.Syms.Lookup(".glink", 0))
+			shsym(sh, ldr, ldr.Lookup(".glink", 0))
 		}
 
 		sh = elfshname(".plt")
@@ -2125,7 +2108,7 @@
 			sh.entsize = 4
 		}
 		sh.addralign = sh.entsize
-		shsym(sh, ctxt.Syms.Lookup(".plt", 0))
+		shsym(sh, ldr, ldr.Lookup(".plt", 0))
 
 		// On ppc64, .got comes from the input files, so don't
 		// create it here, and .got.plt is not used.
@@ -2135,14 +2118,14 @@
 			sh.flags = SHF_ALLOC + SHF_WRITE
 			sh.entsize = uint64(ctxt.Arch.RegSize)
 			sh.addralign = uint64(ctxt.Arch.RegSize)
-			shsym(sh, ctxt.Syms.Lookup(".got", 0))
+			shsym(sh, ldr, ldr.Lookup(".got", 0))
 
 			sh = elfshname(".got.plt")
 			sh.type_ = SHT_PROGBITS
 			sh.flags = SHF_ALLOC + SHF_WRITE
 			sh.entsize = uint64(ctxt.Arch.RegSize)
 			sh.addralign = uint64(ctxt.Arch.RegSize)
-			shsym(sh, ctxt.Syms.Lookup(".got.plt", 0))
+			shsym(sh, ldr, ldr.Lookup(".got.plt", 0))
 		}
 
 		sh = elfshname(".hash")
@@ -2151,7 +2134,7 @@
 		sh.entsize = 4
 		sh.addralign = uint64(ctxt.Arch.RegSize)
 		sh.link = uint32(elfshname(".dynsym").shnum)
-		shsym(sh, ctxt.Syms.Lookup(".hash", 0))
+		shsym(sh, ldr, ldr.Lookup(".hash", 0))
 
 		/* sh and PT_DYNAMIC for .dynamic section */
 		sh = elfshname(".dynamic")
@@ -2161,7 +2144,7 @@
 		sh.entsize = 2 * uint64(ctxt.Arch.RegSize)
 		sh.addralign = uint64(ctxt.Arch.RegSize)
 		sh.link = uint32(elfshname(".dynstr").shnum)
-		shsym(sh, ctxt.Syms.Lookup(".dynamic", 0))
+		shsym(sh, ldr, ldr.Lookup(".dynamic", 0))
 		ph := newElfPhdr()
 		ph.type_ = PT_DYNAMIC
 		ph.flags = PF_R + PF_W
@@ -2205,7 +2188,7 @@
 	sh := elfshname(".shstrtab")
 	sh.type_ = SHT_STRTAB
 	sh.addralign = 1
-	shsym(sh, ctxt.Syms.Lookup(".shstrtab", 0))
+	shsym(sh, ldr, ldr.Lookup(".shstrtab", 0))
 	eh.shstrndx = uint16(sh.shnum)
 
 	// put these sections early in the list
@@ -2244,8 +2227,8 @@
 			elfshreloc(ctxt.Arch, sect)
 		}
 		for _, si := range dwarfp {
-			s := si.secSym()
-			elfshreloc(ctxt.Arch, s.Sect)
+			sect := ldr.SymSect(si.secSym())
+			elfshreloc(ctxt.Arch, sect)
 		}
 		// add a .note.GNU-stack section to mark the stack as non-executable
 		sh := elfshname(".note.GNU-stack")
@@ -2259,7 +2242,7 @@
 		sh := elfshname(".symtab")
 		sh.type_ = SHT_SYMTAB
 		sh.off = uint64(symo)
-		sh.size = uint64(Symsize)
+		sh.size = uint64(symSize)
 		sh.addralign = uint64(ctxt.Arch.RegSize)
 		sh.entsize = 8 + 2*uint64(ctxt.Arch.RegSize)
 		sh.link = uint32(elfshname(".strtab").shnum)
@@ -2267,7 +2250,7 @@
 
 		sh = elfshname(".strtab")
 		sh.type_ = SHT_STRTAB
-		sh.off = uint64(symo) + uint64(Symsize)
+		sh.off = uint64(symo) + uint64(symSize)
 		sh.size = uint64(len(Elfstrdat))
 		sh.addralign = 1
 	}
@@ -2349,12 +2332,12 @@
 	}
 }
 
-func elfadddynsym2(ldr *loader.Loader, target *Target, syms *ArchSyms, s loader.Sym) {
+func elfadddynsym(ldr *loader.Loader, target *Target, syms *ArchSyms, s loader.Sym) {
 	ldr.SetSymDynid(s, int32(Nelfsym))
 	Nelfsym++
-	d := ldr.MakeSymbolUpdater(syms.DynSym2)
+	d := ldr.MakeSymbolUpdater(syms.DynSym)
 	name := ldr.SymExtname(s)
-	dstru := ldr.MakeSymbolUpdater(syms.DynStr2)
+	dstru := ldr.MakeSymbolUpdater(syms.DynStr)
 	st := ldr.SymType(s)
 	cgoeStatic := ldr.AttrCgoExportStatic(s)
 	cgoeDynamic := ldr.AttrCgoExportDynamic(s)
@@ -2397,8 +2380,8 @@
 		dil := ldr.SymDynimplib(s)
 
 		if target.Arch.Family == sys.AMD64 && !cgoeDynamic && dil != "" && !seenlib[dil] {
-			du := ldr.MakeSymbolUpdater(syms.Dynamic2)
-			Elfwritedynent2(target.Arch, du, DT_NEEDED, uint64(dstru.Addstring(dil)))
+			du := ldr.MakeSymbolUpdater(syms.Dynamic)
+			Elfwritedynent(target.Arch, du, DT_NEEDED, uint64(dstru.Addstring(dil)))
 		}
 	} else {
 
diff --git a/src/cmd/link/internal/ld/elf2.go b/src/cmd/link/internal/ld/elf2.go
deleted file mode 100644
index 07b64cf..0000000
--- a/src/cmd/link/internal/ld/elf2.go
+++ /dev/null
@@ -1,79 +0,0 @@
-// 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/link/internal/sym"
-)
-
-// Temporary dumping around for sym.Symbol version of helper
-// functions in elf.go, still being used for some archs/oses.
-// FIXME: get rid of this file when dodata() is completely
-// converted and the sym.Symbol functions are not needed.
-
-func elfsetstring(s *sym.Symbol, str string, off int) {
-	if nelfstr >= len(elfstr) {
-		Errorf(s, "too many elf strings")
-		errorexit()
-	}
-
-	elfstr[nelfstr].s = str
-	elfstr[nelfstr].off = off
-	nelfstr++
-}
-
-func elfrelocsect2(ctxt *Link, sect *sym.Section, syms []*sym.Symbol) {
-	// If main section is SHT_NOBITS, nothing to relocate.
-	// Also nothing to relocate in .shstrtab.
-	if sect.Vaddr >= sect.Seg.Vaddr+sect.Seg.Filelen {
-		return
-	}
-	if sect.Name == ".shstrtab" {
-		return
-	}
-
-	sect.Reloff = uint64(ctxt.Out.Offset())
-	for i, s := range syms {
-		if !s.Attr.Reachable() {
-			continue
-		}
-		if uint64(s.Value) >= sect.Vaddr {
-			syms = syms[i:]
-			break
-		}
-	}
-
-	eaddr := int32(sect.Vaddr + sect.Length)
-	for _, s := range syms {
-		if !s.Attr.Reachable() {
-			continue
-		}
-		if s.Value >= int64(eaddr) {
-			break
-		}
-		for ri := range s.R {
-			r := &s.R[ri]
-			if r.Done {
-				continue
-			}
-			if r.Xsym == nil {
-				Errorf(s, "missing xsym in relocation %#v %#v", r.Sym.Name, s)
-				continue
-			}
-			esr := ElfSymForReloc(ctxt, r.Xsym)
-			if esr == 0 {
-				Errorf(s, "reloc %d (%s) to non-elf symbol %s (outer=%s) %d (%s)", r.Type, sym.RelocName(ctxt.Arch, r.Type), r.Sym.Name, r.Xsym.Name, r.Sym.Type, r.Sym.Type)
-			}
-			if !r.Xsym.Attr.Reachable() {
-				Errorf(s, "unreachable reloc %d (%s) target %v", r.Type, sym.RelocName(ctxt.Arch, r.Type), r.Xsym.Name)
-			}
-			if !thearch.Elfreloc1(ctxt, r, int64(uint64(s.Value+int64(r.Off))-sect.Vaddr)) {
-				Errorf(s, "unsupported obj reloc %d (%s)/%d to %s", r.Type, sym.RelocName(ctxt.Arch, r.Type), r.Siz, r.Sym.Name)
-			}
-		}
-	}
-
-	sect.Rellen = uint64(ctxt.Out.Offset()) - sect.Reloff
-}
diff --git a/src/cmd/link/internal/ld/errors.go b/src/cmd/link/internal/ld/errors.go
index c2c191d..c5ce097 100644
--- a/src/cmd/link/internal/ld/errors.go
+++ b/src/cmd/link/internal/ld/errors.go
@@ -15,12 +15,6 @@
 	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"
-}
-
-type lookupFn func(name string, version int) *sym.Symbol
 type symNameFn func(s loader.Sym) string
 
 // ErrorReporter is used to make error reporting thread safe.
@@ -28,9 +22,7 @@
 	loader.ErrorReporter
 	unresOnce  sync.Once
 	unresSyms  map[unresolvedSymKey]bool
-	unresSyms2 map[unresolvedSymKey2]bool
 	unresMutex sync.Mutex
-	lookup     lookupFn
 	SymName    symNameFn
 }
 
@@ -71,40 +63,3 @@
 		}
 	}
 }
-
-// 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
-		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 := reporter.lookup(r.Sym.Name, v); rs != nil && rs.Type != sym.Sxxx && rs.Type != sym.SXREF {
-					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)
-		}
-	}
-}
diff --git a/src/cmd/link/internal/ld/go.go b/src/cmd/link/internal/ld/go.go
index 9a63a3a..6d05c59 100644
--- a/src/cmd/link/internal/ld/go.go
+++ b/src/cmd/link/internal/ld/go.go
@@ -27,17 +27,6 @@
 	return strings.Replace(t0, `"".`, pkg+".", -1)
 }
 
-func resolveABIAlias(s *sym.Symbol) *sym.Symbol {
-	if s.Type != sym.SABIALIAS {
-		return s
-	}
-	target := s.R[0].Sym
-	if target.Type == sym.SABIALIAS {
-		panic(fmt.Sprintf("ABI alias %s references another ABI alias %s", s, target))
-	}
-	return target
-}
-
 // TODO:
 //	generate debugging section in binary.
 //	once the dust settles, try to move some code to
@@ -50,18 +39,12 @@
 
 	if int64(int(length)) != length {
 		fmt.Fprintf(os.Stderr, "%s: too much pkg data in %s\n", os.Args[0], filename)
-		if *flagU {
-			errorexit()
-		}
 		return
 	}
 
 	bdata := make([]byte, length)
 	if _, err := io.ReadFull(f, bdata); err != nil {
 		fmt.Fprintf(os.Stderr, "%s: short pkg read %s\n", os.Args[0], filename)
-		if *flagU {
-			errorexit()
-		}
 		return
 	}
 	data := string(bdata)
@@ -74,9 +57,6 @@
 		} else {
 			line, data = data, ""
 		}
-		if line == "safe" {
-			lib.Safe = true
-		}
 		if line == "main" {
 			lib.Main = true
 		}
@@ -93,9 +73,6 @@
 		i := strings.IndexByte(data[p0+1:], '\n')
 		if i < 0 {
 			fmt.Fprintf(os.Stderr, "%s: found $$ // cgo but no newline in %s\n", os.Args[0], filename)
-			if *flagU {
-				errorexit()
-			}
 			return
 		}
 		p0 += 1 + i
@@ -106,9 +83,6 @@
 		}
 		if p1 < 0 {
 			fmt.Fprintf(os.Stderr, "%s: cannot find end of // cgo section in %s\n", os.Args[0], filename)
-			if *flagU {
-				errorexit()
-			}
 			return
 		}
 		p1 += p0
@@ -320,24 +294,24 @@
 	seenlib[lib] = true
 
 	if ctxt.IsELF {
-		dsu := ctxt.loader.MakeSymbolUpdater(ctxt.DynStr2)
+		dsu := ctxt.loader.MakeSymbolUpdater(ctxt.DynStr)
 		if dsu.Size() == 0 {
 			dsu.Addstring("")
 		}
-		du := ctxt.loader.MakeSymbolUpdater(ctxt.Dynamic2)
-		Elfwritedynent2(ctxt.Arch, du, DT_NEEDED, uint64(dsu.Addstring(lib)))
+		du := ctxt.loader.MakeSymbolUpdater(ctxt.Dynamic)
+		Elfwritedynent(ctxt.Arch, du, DT_NEEDED, uint64(dsu.Addstring(lib)))
 	} else {
 		Errorf(nil, "adddynlib: unsupported binary format")
 	}
 }
 
-func Adddynsym2(ldr *loader.Loader, target *Target, syms *ArchSyms, s loader.Sym) {
+func Adddynsym(ldr *loader.Loader, target *Target, syms *ArchSyms, s loader.Sym) {
 	if ldr.SymDynid(s) >= 0 || target.LinkMode == LinkExternal {
 		return
 	}
 
 	if target.IsELF {
-		elfadddynsym2(ldr, target, syms, s)
+		elfadddynsym(ldr, target, syms, s)
 	} else if target.HeadType == objabi.Hdarwin {
 		ldr.Errorf(s, "adddynsym: missed symbol (Extname=%s)", ldr.SymExtname(s))
 	} else if target.HeadType == objabi.Hwindows {
@@ -351,19 +325,15 @@
 	var buf bytes.Buffer
 	for i := loader.Sym(1); i < loader.Sym(l.NSym()); i++ {
 		if name := l.SymName(i); strings.HasPrefix(name, "go.track.") {
-			bld := l.MakeSymbolUpdater(i)
-			bld.SetSpecial(true)
-			bld.SetNotInSymbolTable(true)
-			if bld.Reachable() {
+			if l.AttrReachable(i) {
+				l.SetAttrSpecial(i, true)
+				l.SetAttrNotInSymbolTable(i, true)
 				buf.WriteString(name[9:])
 				for p := l.Reachparent[i]; p != 0; p = l.Reachparent[p] {
 					buf.WriteString("\t")
 					buf.WriteString(l.SymName(p))
 				}
 				buf.WriteString("\n")
-
-				bld.SetType(sym.SCONST)
-				bld.SetValue(0)
 			}
 		}
 	}
@@ -383,7 +353,7 @@
 func (ctxt *Link) addexport() {
 	// Track undefined external symbols during external link.
 	if ctxt.LinkMode == LinkExternal {
-		for _, s := range ctxt.Textp2 {
+		for _, s := range ctxt.Textp {
 			if ctxt.loader.AttrSpecial(s) || ctxt.loader.AttrSubSymbol(s) {
 				continue
 			}
@@ -408,8 +378,8 @@
 		return
 	}
 
-	for _, exp := range ctxt.dynexp2 {
-		Adddynsym2(ctxt.loader, &ctxt.Target, &ctxt.ArchSyms, exp)
+	for _, exp := range ctxt.dynexp {
+		Adddynsym(ctxt.loader, &ctxt.Target, &ctxt.ArchSyms, exp)
 	}
 	for _, lib := range dynlib {
 		adddynlib(ctxt, lib)
diff --git a/src/cmd/link/internal/ld/heap.go b/src/cmd/link/internal/ld/heap.go
new file mode 100644
index 0000000..ea2d772
--- /dev/null
+++ b/src/cmd/link/internal/ld/heap.go
@@ -0,0 +1,54 @@
+// 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/link/internal/loader"
+
+// Min-heap implementation, for the deadcode pass.
+// Specialized for loader.Sym elements.
+
+type heap []loader.Sym
+
+func (h *heap) push(s loader.Sym) {
+	*h = append(*h, s)
+	// sift up
+	n := len(*h) - 1
+	for n > 0 {
+		p := (n - 1) / 2 // parent
+		if (*h)[p] <= (*h)[n] {
+			break
+		}
+		(*h)[n], (*h)[p] = (*h)[p], (*h)[n]
+		n = p
+	}
+}
+
+func (h *heap) pop() loader.Sym {
+	r := (*h)[0]
+	n := len(*h) - 1
+	(*h)[0] = (*h)[n]
+	*h = (*h)[:n]
+
+	// sift down
+	i := 0
+	for {
+		c := 2*i + 1 // left child
+		if c >= n {
+			break
+		}
+		if c1 := c + 1; c1 < n && (*h)[c1] < (*h)[c] {
+			c = c1 // right child
+		}
+		if (*h)[i] <= (*h)[c] {
+			break
+		}
+		(*h)[i], (*h)[c] = (*h)[c], (*h)[i]
+		i = c
+	}
+
+	return r
+}
+
+func (h *heap) empty() bool { return len(*h) == 0 }
diff --git a/src/cmd/link/internal/ld/heap_test.go b/src/cmd/link/internal/ld/heap_test.go
new file mode 100644
index 0000000..08c9030
--- /dev/null
+++ b/src/cmd/link/internal/ld/heap_test.go
@@ -0,0 +1,90 @@
+// 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/link/internal/loader"
+	"testing"
+)
+
+func TestHeap(t *testing.T) {
+	tests := [][]loader.Sym{
+		{10, 20, 30, 40, 50, 60, 70, 80, 90, 100},
+		{100, 90, 80, 70, 60, 50, 40, 30, 20, 10},
+		{30, 50, 80, 20, 60, 70, 10, 100, 90, 40},
+	}
+	for _, s := range tests {
+		h := heap{}
+		for _, i := range s {
+			h.push(i)
+			if !verify(&h, 0) {
+				t.Errorf("heap invariant violated: %v", h)
+			}
+		}
+		for j := 0; j < len(s); j++ {
+			x := h.pop()
+			if !verify(&h, 0) {
+				t.Errorf("heap invariant violated: %v", h)
+			}
+			// pop should return elements in ascending order.
+			if want := loader.Sym((j + 1) * 10); x != want {
+				t.Errorf("pop returns wrong element: want %d, got %d", want, x)
+			}
+		}
+		if !h.empty() {
+			t.Errorf("heap is not empty after all pops")
+		}
+	}
+
+	// Also check that mixed pushes and pops work correctly.
+	for _, s := range tests {
+		h := heap{}
+		for i := 0; i < len(s)/2; i++ {
+			// two pushes, one pop
+			h.push(s[2*i])
+			if !verify(&h, 0) {
+				t.Errorf("heap invariant violated: %v", h)
+			}
+			h.push(s[2*i+1])
+			if !verify(&h, 0) {
+				t.Errorf("heap invariant violated: %v", h)
+			}
+			h.pop()
+			if !verify(&h, 0) {
+				t.Errorf("heap invariant violated: %v", h)
+			}
+		}
+		for !h.empty() { // pop remaining elements
+			h.pop()
+			if !verify(&h, 0) {
+				t.Errorf("heap invariant violated: %v", h)
+			}
+		}
+	}
+}
+
+// recursively verify heap-ness, starting at element i.
+func verify(h *heap, i int) bool {
+	n := len(*h)
+	c1 := 2*i + 1 // left child
+	c2 := 2*i + 2 // right child
+	if c1 < n {
+		if (*h)[c1] < (*h)[i] {
+			return false
+		}
+		if !verify(h, c1) {
+			return false
+		}
+	}
+	if c2 < n {
+		if (*h)[c2] < (*h)[i] {
+			return false
+		}
+		if !verify(h, c2) {
+			return false
+		}
+	}
+	return true
+}
diff --git a/src/cmd/link/internal/ld/ld.go b/src/cmd/link/internal/ld/ld.go
index 71f388b..0846439 100644
--- a/src/cmd/link/internal/ld/ld.go
+++ b/src/cmd/link/internal/ld/ld.go
@@ -248,11 +248,11 @@
 	ctxt.loader.SetAttrLocal(ifs, true)
 	initfunc.SetType(sym.STEXT)
 
-	// Add the init func and/or addmoduledata to Textp2.
+	// Add the init func and/or addmoduledata to Textp.
 	if ctxt.BuildMode == BuildModePlugin {
-		ctxt.Textp2 = append(ctxt.Textp2, amd)
+		ctxt.Textp = append(ctxt.Textp, amd)
 	}
-	ctxt.Textp2 = append(ctxt.Textp2, initfunc.Sym())
+	ctxt.Textp = append(ctxt.Textp, initfunc.Sym())
 
 	// Create an init array entry
 	amdi := ctxt.loader.LookupOrCreateSym("go.link.addmoduledatainit", 0)
diff --git a/src/cmd/link/internal/ld/lib.go b/src/cmd/link/internal/ld/lib.go
index 61ccc28..a747cde 100644
--- a/src/cmd/link/internal/ld/lib.go
+++ b/src/cmd/link/internal/ld/lib.go
@@ -48,7 +48,6 @@
 	"debug/macho"
 	"encoding/base64"
 	"encoding/binary"
-	"encoding/hex"
 	"fmt"
 	"io"
 	"io/ioutil"
@@ -94,100 +93,56 @@
 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 // THE SOFTWARE.
 
-type LookupFn func(name string, version int) *sym.Symbol
-
 // ArchSyms holds a number of architecture specific symbols used during
 // relocation.  Rather than allowing them universal access to all symbols,
 // we keep a subset for relocation application.
 type ArchSyms struct {
-	TOC    *sym.Symbol
-	DotTOC []*sym.Symbol // for each version
+	Rel     loader.Sym
+	Rela    loader.Sym
+	RelPLT  loader.Sym
+	RelaPLT loader.Sym
 
-	GOT    *sym.Symbol
-	PLT    *sym.Symbol
-	GOTPLT *sym.Symbol
+	LinkEditGOT loader.Sym
+	LinkEditPLT loader.Sym
 
-	Tlsg      *sym.Symbol
+	TOC    loader.Sym
+	DotTOC []loader.Sym // for each version
+
+	GOT    loader.Sym
+	PLT    loader.Sym
+	GOTPLT loader.Sym
+
+	Tlsg      loader.Sym
 	Tlsoffset int
 
-	Dynamic *sym.Symbol
-	DynSym  *sym.Symbol
-	DynStr  *sym.Symbol
-
-	// Elf specific
-	Rel     *sym.Symbol
-	Rela    *sym.Symbol
-	RelPLT  *sym.Symbol
-	RelaPLT *sym.Symbol
-
-	// Darwin symbols
-	LinkEditGOT *sym.Symbol
-	LinkEditPLT *sym.Symbol
-
-	// ----- loader.Sym equivalents -----
-
-	Rel2     loader.Sym
-	Rela2    loader.Sym
-	RelPLT2  loader.Sym
-	RelaPLT2 loader.Sym
-
-	LinkEditGOT2 loader.Sym
-	LinkEditPLT2 loader.Sym
-
-	TOC2    loader.Sym
-	DotTOC2 []loader.Sym // for each version
-
-	GOT2    loader.Sym
-	PLT2    loader.Sym
-	GOTPLT2 loader.Sym
-
-	Tlsg2 loader.Sym
-
-	Dynamic2 loader.Sym
-	DynSym2  loader.Sym
-	DynStr2  loader.Sym
+	Dynamic loader.Sym
+	DynSym  loader.Sym
+	DynStr  loader.Sym
 }
 
-const BeforeLoadlibFull = 1
-const AfterLoadlibFull = 2
-
-// mkArchSym is a helper for setArchSyms, invoked once before loadlibfull
-// and once after. On the first call it creates a loader.Sym with the
-// specified name, and on the second call a corresponding sym.Symbol.
-func (ctxt *Link) mkArchSym(which int, name string, ver int, ls *loader.Sym, ss **sym.Symbol) {
-	if which == BeforeLoadlibFull {
-		*ls = ctxt.loader.LookupOrCreateSym(name, ver)
-	} else {
-		*ss = ctxt.loader.Syms[*ls]
-	}
+// mkArchSym is a helper for setArchSyms, to set up a special symbol.
+func (ctxt *Link) mkArchSym(name string, ver int, ls *loader.Sym) {
+	*ls = ctxt.loader.LookupOrCreateSym(name, ver)
 }
 
 // mkArchVecSym is similar to  setArchSyms, but operates on elements within
 // a slice, where each element corresponds to some symbol version.
-func (ctxt *Link) mkArchSymVec(which int, name string, ver int, ls []loader.Sym, ss []*sym.Symbol) {
-	if which == BeforeLoadlibFull {
-		ls[ver] = ctxt.loader.LookupOrCreateSym(name, ver)
-	} else if ls[ver] != 0 {
-		ss[ver] = ctxt.loader.Syms[ls[ver]]
-	}
+func (ctxt *Link) mkArchSymVec(name string, ver int, ls []loader.Sym) {
+	ls[ver] = ctxt.loader.LookupOrCreateSym(name, ver)
 }
 
 // setArchSyms sets up the ArchSyms structure, and must be called before
-// relocations are applied. This function is invoked twice, once prior
-// to loadlibfull(), and once after the work of loadlibfull is complete.
-func (ctxt *Link) setArchSyms(which int) {
-	if which != BeforeLoadlibFull && which != AfterLoadlibFull {
-		panic("internal error")
-	}
-	ctxt.mkArchSym(which, ".got", 0, &ctxt.GOT2, &ctxt.GOT)
-	ctxt.mkArchSym(which, ".plt", 0, &ctxt.PLT2, &ctxt.PLT)
-	ctxt.mkArchSym(which, ".got.plt", 0, &ctxt.GOTPLT2, &ctxt.GOTPLT)
-	ctxt.mkArchSym(which, ".dynamic", 0, &ctxt.Dynamic2, &ctxt.Dynamic)
-	ctxt.mkArchSym(which, ".dynsym", 0, &ctxt.DynSym2, &ctxt.DynSym)
-	ctxt.mkArchSym(which, ".dynstr", 0, &ctxt.DynStr2, &ctxt.DynStr)
+// relocations are applied.
+func (ctxt *Link) setArchSyms() {
+	ctxt.mkArchSym(".got", 0, &ctxt.GOT)
+	ctxt.mkArchSym(".plt", 0, &ctxt.PLT)
+	ctxt.mkArchSym(".got.plt", 0, &ctxt.GOTPLT)
+	ctxt.mkArchSym(".dynamic", 0, &ctxt.Dynamic)
+	ctxt.mkArchSym(".dynsym", 0, &ctxt.DynSym)
+	ctxt.mkArchSym(".dynstr", 0, &ctxt.DynStr)
 
 	if ctxt.IsPPC64() {
-		ctxt.mkArchSym(which, "TOC", 0, &ctxt.TOC2, &ctxt.TOC)
+		ctxt.mkArchSym("TOC", 0, &ctxt.TOC)
 
 		// NB: note the +2 below for DotTOC2 compared to the +1 for
 		// DocTOC. This is because loadlibfull() creates an additional
@@ -195,27 +150,24 @@
 		// *sym.Symbol symbols. Symbols that are assigned this final
 		// version are not going to have TOC references, so it should
 		// be ok for them to inherit an invalid .TOC. symbol.
-		if which == BeforeLoadlibFull {
-			ctxt.DotTOC2 = make([]loader.Sym, ctxt.Syms.MaxVersion()+2)
-		} else {
-			ctxt.DotTOC = make([]*sym.Symbol, ctxt.Syms.MaxVersion()+1)
-		}
-		for i := 0; i <= ctxt.Syms.MaxVersion(); i++ {
+		// TODO: revisit the +2, now that loadlibfull is gone.
+		ctxt.DotTOC = make([]loader.Sym, ctxt.MaxVersion()+2)
+		for i := 0; i <= ctxt.MaxVersion(); i++ {
 			if i >= 2 && i < sym.SymVerStatic { // these versions are not used currently
 				continue
 			}
-			ctxt.mkArchSymVec(which, ".TOC.", i, ctxt.DotTOC2, ctxt.DotTOC)
+			ctxt.mkArchSymVec(".TOC.", i, ctxt.DotTOC)
 		}
 	}
 	if ctxt.IsElf() {
-		ctxt.mkArchSym(which, ".rel", 0, &ctxt.Rel2, &ctxt.Rel)
-		ctxt.mkArchSym(which, ".rela", 0, &ctxt.Rela2, &ctxt.Rela)
-		ctxt.mkArchSym(which, ".rel.plt", 0, &ctxt.RelPLT2, &ctxt.RelPLT)
-		ctxt.mkArchSym(which, ".rela.plt", 0, &ctxt.RelaPLT2, &ctxt.RelaPLT)
+		ctxt.mkArchSym(".rel", 0, &ctxt.Rel)
+		ctxt.mkArchSym(".rela", 0, &ctxt.Rela)
+		ctxt.mkArchSym(".rel.plt", 0, &ctxt.RelPLT)
+		ctxt.mkArchSym(".rela.plt", 0, &ctxt.RelaPLT)
 	}
 	if ctxt.IsDarwin() {
-		ctxt.mkArchSym(which, ".linkedit.got", 0, &ctxt.LinkEditGOT2, &ctxt.LinkEditGOT)
-		ctxt.mkArchSym(which, ".linkedit.plt", 0, &ctxt.LinkEditPLT2, &ctxt.LinkEditPLT)
+		ctxt.mkArchSym(".linkedit.got", 0, &ctxt.LinkEditGOT)
+		ctxt.mkArchSym(".linkedit.plt", 0, &ctxt.LinkEditPLT)
 	}
 }
 
@@ -232,9 +184,22 @@
 	Openbsddynld   string
 	Dragonflydynld string
 	Solarisdynld   string
-	Adddynrel      func(*Target, *loader.Loader, *ArchSyms, *sym.Symbol, *sym.Reloc) bool
-	Adddynrel2     func(*Target, *loader.Loader, *ArchSyms, loader.Sym, loader.Reloc2, int) bool
-	Archinit       func(*Link)
+
+	// Empty spaces between codeblocks will be padded with this value.
+	// For example an architecture might want to pad with a trap instruction to
+	// catch wayward programs. Architectures that do not define a padding value
+	// are padded with zeros.
+	CodePad []byte
+
+	// Set to true to write all text blocks in with CodeBlkWrite
+	WriteTextBlocks bool
+
+	// Plan 9 variables.
+	Plan9Magic  uint32
+	Plan9_64Bit bool
+
+	Adddynrel func(*Target, *loader.Loader, *ArchSyms, loader.Sym, loader.Reloc2, int) bool
+	Archinit  func(*Link)
 	// Archreloc is an arch-specific hook that assists in relocation processing
 	// (invoked by 'relocsym'); it handles target-specific relocation tasks.
 	// Here "rel" is the current relocation being examined, "sym" is the symbol
@@ -244,9 +209,8 @@
 	// same spot in sym.P), a boolean indicating if the external relocations'
 	// been used, and a boolean indicating success/failure (a failing value
 	// indicates a fatal error).
-	Archreloc func(target *Target, syms *ArchSyms, rel *sym.Reloc, sym *sym.Symbol,
-		offset int64) (relocatedOffset int64, success bool)
-	Archreloc2 func(*Target, *loader.Loader, *ArchSyms, loader.Reloc2, *loader.ExtReloc, loader.Sym, int64) (int64, bool, bool)
+	Archreloc func(*Target, *loader.Loader, *ArchSyms, loader.Reloc2, *loader.ExtReloc,
+		loader.Sym, int64) (relocatedOffset int64, needExtReloc bool, ok bool)
 	// Archrelocvariant is a second arch-specific hook used for
 	// relocation processing; it handles relocations where r.Type is
 	// insufficient to describe the relocation (r.Variant !=
@@ -255,28 +219,29 @@
 	// relocation applies, and "off" is the contents of the
 	// to-be-relocated data item (from sym.P). Return is an updated
 	// offset value.
-	Archrelocvariant func(target *Target, syms *ArchSyms, rel *sym.Reloc, sym *sym.Symbol,
-		offset int64) (relocatedOffset int64)
+	Archrelocvariant func(target *Target, ldr *loader.Loader, rel loader.Reloc2,
+		rv sym.RelocVariant, sym loader.Sym, offset int64) (relocatedOffset int64)
 
 	// Generate a trampoline for a call from s to rs if necessary. ri is
 	// index of the relocation.
 	Trampoline func(ctxt *Link, ldr *loader.Loader, ri int, rs, s loader.Sym)
 
-	// Asmb and Asmb2 are arch-specific routines that write the output
-	// file. Typically, Asmb writes most of the content (sections and
-	// segments), for which we have computed the size and offset. Asmb2
-	// writes the rest.
+	// Assembling the binary breaks into two phases, writing the code/data/
+	// dwarf information (which is rather generic), and some more architecture
+	// specific work like setting up the elf headers/dynamic relocations, etc.
+	// The phases are called "Asmb" and "Asmb2". Asmb2 needs to be defined for
+	// every architecture, but only if architecture has an Asmb function will
+	// it be used for assembly.  Otherwise a generic assembly Asmb function is
+	// used.
 	Asmb  func(*Link, *loader.Loader)
-	Asmb2 func(*Link)
+	Asmb2 func(*Link, *loader.Loader)
 
-	Elfreloc1   func(*Link, *sym.Reloc, int64) bool
-	Elfreloc2   func(*Link, *loader.Loader, loader.Sym, loader.ExtRelocView, int64) bool
+	Elfreloc1   func(*Link, *loader.Loader, loader.Sym, loader.ExtRelocView, int64) bool
 	Elfsetupplt func(ctxt *Link, plt, gotplt *loader.SymbolBuilder, dynamic loader.Sym)
-	Gentext     func(*Link)
-	Gentext2    func(*Link, *loader.Loader)
-	Machoreloc1 func(*sys.Arch, *OutBuf, *sym.Symbol, *sym.Reloc, int64) bool
-	PEreloc1    func(*sys.Arch, *OutBuf, *sym.Symbol, *sym.Reloc, int64) bool
-	Xcoffreloc1 func(*sys.Arch, *OutBuf, *sym.Symbol, *sym.Reloc, int64) bool
+	Gentext     func(*Link, *loader.Loader)
+	Machoreloc1 func(*sys.Arch, *OutBuf, *loader.Loader, loader.Sym, loader.ExtRelocView, int64) bool
+	PEreloc1    func(*sys.Arch, *OutBuf, *loader.Loader, loader.Sym, loader.ExtRelocView, int64) bool
+	Xcoffreloc1 func(*sys.Arch, *OutBuf, *loader.Loader, loader.Sym, loader.ExtRelocView, int64) bool
 
 	// TLSIEtoLE converts a TLS Initial Executable relocation to
 	// a TLS Local Executable relocation.
@@ -292,10 +257,10 @@
 
 var (
 	thearch Arch
-	Lcsize  int32
+	lcSize  int32
 	rpath   Rpath
-	Spsize  int32
-	Symsize int32
+	spSize  int32
+	symSize int32
 )
 
 const (
@@ -320,7 +285,6 @@
 }
 
 var (
-	dynexp          []*sym.Symbol
 	dynlib          []string
 	ldflag          []string
 	havedynamic     int
@@ -508,7 +472,8 @@
 	default:
 		log.Fatalf("invalid -strictdups flag value %d", *FlagStrictDups)
 	}
-	ctxt.loader = loader.NewLoader(flags, elfsetstring, &ctxt.ErrorReporter.ErrorReporter)
+	elfsetstring1 := func(str string, off int) { elfsetstring(ctxt, 0, str, off) }
+	ctxt.loader = loader.NewLoader(flags, elfsetstring1, &ctxt.ErrorReporter.ErrorReporter)
 	ctxt.ErrorReporter.SymName = func(s loader.Sym) string {
 		return ctxt.loader.SymName(s)
 	}
@@ -638,15 +603,6 @@
 	strictDupMsgCount = ctxt.loader.NStrictDupMsgs()
 }
 
-// genSymsForDynexp constructs a *sym.Symbol version of ctxt.dynexp,
-// writing to the global variable 'dynexp'.
-func genSymsForDynexp(ctxt *Link) {
-	dynexp = make([]*sym.Symbol, len(ctxt.dynexp2))
-	for i, s := range ctxt.dynexp2 {
-		dynexp[i] = ctxt.loader.Syms[s]
-	}
-}
-
 // setupdynexp constructs ctxt.dynexp, a list of loader.Sym.
 func setupdynexp(ctxt *Link) {
 	dynexpMap := ctxt.cgo_export_dynamic
@@ -678,7 +634,7 @@
 		ctxt.loader.SetSymExtname(t, ctxt.loader.SymExtname(s))
 		d[i] = t
 	}
-	ctxt.dynexp2 = d
+	ctxt.dynexp = d
 
 	ctxt.cgo_export_static = nil
 	ctxt.cgo_export_dynamic = nil
@@ -777,7 +733,7 @@
 			Errorf(nil, "runtime declared tlsg variable %v", sb.Type())
 		}
 		ctxt.loader.SetAttrReachable(tlsg, true)
-		ctxt.Tlsg2 = tlsg
+		ctxt.Tlsg = tlsg
 	}
 
 	var moduledata loader.Sym
@@ -826,17 +782,7 @@
 	// the GC.
 	mdsb.SetType(sym.SNOPTRDATA)
 	ctxt.loader.SetAttrReachable(moduledata, true)
-	ctxt.Moduledata2 = moduledata
-
-	// If package versioning is required, generate a hash of the
-	// packages used in the link.
-	if ctxt.BuildMode == BuildModeShared || ctxt.BuildMode == BuildModePlugin || ctxt.CanUsePlugins() {
-		for _, lib := range ctxt.Library {
-			if lib.Shlib == "" {
-				genhash(ctxt, lib)
-			}
-		}
-	}
+	ctxt.Moduledata = moduledata
 
 	if ctxt.Arch == sys.Arch386 && ctxt.HeadType != objabi.Hwindows {
 		if (ctxt.BuildMode == BuildModeCArchive && ctxt.IsELF) || ctxt.BuildMode == BuildModeCShared || ctxt.BuildMode == BuildModePIE || ctxt.DynlinkingGo() {
@@ -847,7 +793,7 @@
 		}
 	}
 
-	// DWARF-gen and other phases require that the unit Textp2 slices
+	// DWARF-gen and other phases require that the unit Textp slices
 	// be populated, so that it can walk the functions in each unit.
 	// Call into the loader to do this (requires that we collect the
 	// set of internal libraries first). NB: might be simpler if we
@@ -858,7 +804,7 @@
 	for _, lib := range ctxt.Library {
 		intlibs = append(intlibs, isRuntimeDepPkg(lib.Pkg))
 	}
-	ctxt.Textp2 = ctxt.loader.AssignTextSymbolOrder(ctxt.Library, intlibs, ctxt.Textp2)
+	ctxt.Textp = ctxt.loader.AssignTextSymbolOrder(ctxt.Library, intlibs, ctxt.Textp)
 }
 
 // mangleTypeSym shortens the names of symbols that represent Go types
@@ -962,67 +908,6 @@
 	return arsize + SAR_HDR
 }
 
-func genhash(ctxt *Link, lib *sym.Library) {
-	f, err := bio.Open(lib.File)
-	if err != nil {
-		Errorf(nil, "cannot open file %s for hash generation: %v", lib.File, err)
-		return
-	}
-	defer f.Close()
-
-	var magbuf [len(ARMAG)]byte
-	if _, err := io.ReadFull(f, magbuf[:]); err != nil {
-		Exitf("file %s too short", lib.File)
-	}
-
-	if string(magbuf[:]) != ARMAG {
-		Exitf("%s is not an archive file", lib.File)
-	}
-
-	var arhdr ArHdr
-	l := nextar(f, f.Offset(), &arhdr)
-	if l <= 0 {
-		Errorf(nil, "%s: short read on archive file symbol header", lib.File)
-		return
-	}
-	if arhdr.name != pkgdef {
-		Errorf(nil, "%s: missing package data entry", lib.File)
-		return
-	}
-
-	h := sha1.New()
-
-	// To compute the hash of a package, we hash the first line of
-	// __.PKGDEF (which contains the toolchain version and any
-	// GOEXPERIMENT flags) and the export data (which is between
-	// the first two occurrences of "\n$$").
-
-	pkgDefBytes := make([]byte, atolwhex(arhdr.size))
-	_, err = io.ReadFull(f, pkgDefBytes)
-	if err != nil {
-		Errorf(nil, "%s: error reading package data: %v", lib.File, err)
-		return
-	}
-	firstEOL := bytes.IndexByte(pkgDefBytes, '\n')
-	if firstEOL < 0 {
-		Errorf(nil, "cannot parse package data of %s for hash generation, no newline found", lib.File)
-		return
-	}
-	firstDoubleDollar := bytes.Index(pkgDefBytes, []byte("\n$$"))
-	if firstDoubleDollar < 0 {
-		Errorf(nil, "cannot parse package data of %s for hash generation, no \\n$$ found", lib.File)
-		return
-	}
-	secondDoubleDollar := bytes.Index(pkgDefBytes[firstDoubleDollar+1:], []byte("\n$$"))
-	if secondDoubleDollar < 0 {
-		Errorf(nil, "cannot parse package data of %s for hash generation, only one \\n$$ found", lib.File)
-		return
-	}
-	h.Write(pkgDefBytes[0:firstEOL])
-	h.Write(pkgDefBytes[firstDoubleDollar : firstDoubleDollar+secondDoubleDollar])
-	lib.Hash = hex.EncodeToString(h.Sum(nil))
-}
-
 func loadobjfile(ctxt *Link, lib *sym.Library) {
 	pkg := objabi.PathToPrefix(lib.Pkg)
 
@@ -1038,21 +923,6 @@
 		if pkg == "main" && !lib.Main {
 			Exitf("%s: not package main", lib.File)
 		}
-
-		// Ideally, we'd check that *all* object files within
-		// the archive were marked safe, but here we settle
-		// for *any*.
-		//
-		// Historically, cmd/link only checked the __.PKGDEF
-		// file, which in turn came from the first object
-		// file, typically produced by cmd/compile. The
-		// remaining object files are normally produced by
-		// cmd/asm, which doesn't support marking files as
-		// safe anyway. So at least in practice, this matches
-		// how safe mode has always worked.
-		if *flagU && !lib.Safe {
-			Exitf("%s: load of unsafe package %s", lib.File, pkg)
-		}
 	}()
 
 	for i := 0; i < len(ARMAG); i++ {
@@ -1868,32 +1738,32 @@
 	magic := uint32(c1)<<24 | uint32(c2)<<16 | uint32(c3)<<8 | uint32(c4)
 	if magic == 0x7f454c46 { // \x7F E L F
 		ldelf := func(ctxt *Link, f *bio.Reader, pkg string, length int64, pn string) {
-			textp, flags, err := loadelf.Load(ctxt.loader, ctxt.Arch, ctxt.Syms.IncVersion(), f, pkg, length, pn, ehdr.flags)
+			textp, flags, err := loadelf.Load(ctxt.loader, ctxt.Arch, ctxt.IncVersion(), f, pkg, length, pn, ehdr.flags)
 			if err != nil {
 				Errorf(nil, "%v", err)
 				return
 			}
 			ehdr.flags = flags
-			ctxt.Textp2 = append(ctxt.Textp2, textp...)
+			ctxt.Textp = append(ctxt.Textp, textp...)
 		}
 		return ldhostobj(ldelf, ctxt.HeadType, f, pkg, length, pn, file)
 	}
 
 	if magic&^1 == 0xfeedface || magic&^0x01000000 == 0xcefaedfe {
 		ldmacho := func(ctxt *Link, f *bio.Reader, pkg string, length int64, pn string) {
-			textp, err := loadmacho.Load(ctxt.loader, ctxt.Arch, ctxt.Syms.IncVersion(), f, pkg, length, pn)
+			textp, err := loadmacho.Load(ctxt.loader, ctxt.Arch, ctxt.IncVersion(), f, pkg, length, pn)
 			if err != nil {
 				Errorf(nil, "%v", err)
 				return
 			}
-			ctxt.Textp2 = append(ctxt.Textp2, textp...)
+			ctxt.Textp = append(ctxt.Textp, textp...)
 		}
 		return ldhostobj(ldmacho, ctxt.HeadType, f, pkg, length, pn, file)
 	}
 
 	if c1 == 0x4c && c2 == 0x01 || c1 == 0x64 && c2 == 0x86 {
 		ldpe := func(ctxt *Link, f *bio.Reader, pkg string, length int64, pn string) {
-			textp, rsrc, err := loadpe.Load(ctxt.loader, ctxt.Arch, ctxt.Syms.IncVersion(), f, pkg, length, pn)
+			textp, rsrc, err := loadpe.Load(ctxt.loader, ctxt.Arch, ctxt.IncVersion(), f, pkg, length, pn)
 			if err != nil {
 				Errorf(nil, "%v", err)
 				return
@@ -1901,19 +1771,19 @@
 			if rsrc != 0 {
 				setpersrc(ctxt, rsrc)
 			}
-			ctxt.Textp2 = append(ctxt.Textp2, textp...)
+			ctxt.Textp = append(ctxt.Textp, textp...)
 		}
 		return ldhostobj(ldpe, ctxt.HeadType, f, pkg, length, pn, file)
 	}
 
 	if c1 == 0x01 && (c2 == 0xD7 || c2 == 0xF7) {
 		ldxcoff := func(ctxt *Link, f *bio.Reader, pkg string, length int64, pn string) {
-			textp, err := loadxcoff.Load(ctxt.loader, ctxt.Arch, ctxt.Syms.IncVersion(), f, pkg, length, pn)
+			textp, err := loadxcoff.Load(ctxt.loader, ctxt.Arch, ctxt.IncVersion(), f, pkg, length, pn)
 			if err != nil {
 				Errorf(nil, "%v", err)
 				return
 			}
-			ctxt.Textp2 = append(ctxt.Textp2, textp...)
+			ctxt.Textp = append(ctxt.Textp, textp...)
 		}
 		return ldhostobj(ldxcoff, ctxt.HeadType, f, pkg, length, pn, file)
 	}
@@ -2000,7 +1870,7 @@
 	ldpkg(ctxt, f, lib, import1-import0-2, pn) // -2 for !\n
 	f.MustSeek(import1, 0)
 
-	fingerprint := ctxt.loader.Preload(ctxt.Syms, f, lib, unit, eof-f.Offset())
+	fingerprint := ctxt.loader.Preload(ctxt.IncVersion(), f, lib, unit, eof-f.Offset())
 	if !fingerprint.IsZero() { // Assembly objects don't have fingerprints. Ignore them.
 		// Check fingerprint, to ensure the importing and imported packages
 		// have consistent view of symbol indices.
@@ -2313,14 +2183,14 @@
 
 	// Check every function, but do the nosplit functions in a first pass,
 	// to make the printed failure chains as short as possible.
-	for _, s := range ctxt.Textp2 {
+	for _, s := range ctxt.Textp {
 		if ldr.IsNoSplit(s) {
 			ch.sym = s
 			sc.check(&ch, 0)
 		}
 	}
 
-	for _, s := range ctxt.Textp2 {
+	for _, s := range ctxt.Textp {
 		if !ldr.IsNoSplit(s) {
 			ch.sym = s
 			sc.check(&ch, 0)
@@ -2489,7 +2359,7 @@
 	Exit(2)
 }
 
-type SymbolType int8
+type SymbolType int8 // TODO: after genasmsym is gone, maybe rename to plan9typeChar or something
 
 const (
 	// see also https://9p.io/magic/man2html/1/nm
@@ -2506,165 +2376,7 @@
 	DeletedAutoSym = 'x'
 )
 
-func genasmsym(ctxt *Link, put func(*Link, *sym.Symbol, string, SymbolType, int64)) {
-	// These symbols won't show up in the first loop below because we
-	// skip sym.STEXT symbols. Normal sym.STEXT symbols are emitted by walking textp.
-	s := ctxt.Syms.Lookup("runtime.text", 0)
-	if s.Type == sym.STEXT {
-		// We've already included this symbol in ctxt.Textp
-		// if ctxt.DynlinkingGo() && ctxt.HeadType == objabi.Hdarwin or
-		// on AIX with external linker.
-		// See data.go:/textaddress
-		if !(ctxt.DynlinkingGo() && ctxt.HeadType == objabi.Hdarwin) && !(ctxt.HeadType == objabi.Haix && ctxt.LinkMode == LinkExternal) {
-			put(ctxt, s, s.Name, TextSym, s.Value)
-		}
-	}
-
-	n := 0
-
-	// Generate base addresses for all text sections if there are multiple
-	for _, sect := range Segtext.Sections {
-		if n == 0 {
-			n++
-			continue
-		}
-		if sect.Name != ".text" || (ctxt.HeadType == objabi.Haix && ctxt.LinkMode == LinkExternal) {
-			// On AIX, runtime.text.X are symbols already in the symtab.
-			break
-		}
-		s = ctxt.Syms.ROLookup(fmt.Sprintf("runtime.text.%d", n), 0)
-		if s == nil {
-			break
-		}
-		if s.Type == sym.STEXT {
-			put(ctxt, s, s.Name, TextSym, s.Value)
-		}
-		n++
-	}
-
-	s = ctxt.Syms.Lookup("runtime.etext", 0)
-	if s.Type == sym.STEXT {
-		// We've already included this symbol in ctxt.Textp
-		// if ctxt.DynlinkingGo() && ctxt.HeadType == objabi.Hdarwin or
-		// on AIX with external linker.
-		// See data.go:/textaddress
-		if !(ctxt.DynlinkingGo() && ctxt.HeadType == objabi.Hdarwin) && !(ctxt.HeadType == objabi.Haix && ctxt.LinkMode == LinkExternal) {
-			put(ctxt, s, s.Name, TextSym, s.Value)
-		}
-	}
-
-	shouldBeInSymbolTable := func(s *sym.Symbol) bool {
-		if s.Attr.NotInSymbolTable() {
-			return false
-		}
-		if ctxt.HeadType == objabi.Haix && s.Name == ".go.buildinfo" {
-			// On AIX, .go.buildinfo must be in the symbol table as
-			// it has relocations.
-			return true
-		}
-		if (s.Name == "" || s.Name[0] == '.') && !s.IsFileLocal() && s.Name != ".rathole" && s.Name != ".TOC." {
-			return false
-		}
-		return true
-	}
-
-	for _, s := range ctxt.loader.Syms {
-		if s == nil {
-			continue
-		}
-		if !shouldBeInSymbolTable(s) {
-			continue
-		}
-		switch s.Type {
-		case sym.SCONST,
-			sym.SRODATA,
-			sym.SSYMTAB,
-			sym.SPCLNTAB,
-			sym.SINITARR,
-			sym.SDATA,
-			sym.SNOPTRDATA,
-			sym.SELFROSECT,
-			sym.SMACHOGOT,
-			sym.STYPE,
-			sym.SSTRING,
-			sym.SGOSTRING,
-			sym.SGOFUNC,
-			sym.SGCBITS,
-			sym.STYPERELRO,
-			sym.SSTRINGRELRO,
-			sym.SGOSTRINGRELRO,
-			sym.SGOFUNCRELRO,
-			sym.SGCBITSRELRO,
-			sym.SRODATARELRO,
-			sym.STYPELINK,
-			sym.SITABLINK,
-			sym.SWINDOWS:
-			if !s.Attr.Reachable() {
-				continue
-			}
-			put(ctxt, s, s.Name, DataSym, Symaddr(s))
-
-		case sym.SBSS, sym.SNOPTRBSS, sym.SLIBFUZZER_EXTRA_COUNTER:
-			if !s.Attr.Reachable() {
-				continue
-			}
-			if len(s.P) > 0 {
-				Errorf(s, "should not be bss (size=%d type=%v special=%v)", len(s.P), s.Type, s.Attr.Special())
-			}
-			put(ctxt, s, s.Name, BSSSym, Symaddr(s))
-
-		case sym.SUNDEFEXT:
-			if ctxt.HeadType == objabi.Hwindows || ctxt.HeadType == objabi.Haix || ctxt.IsELF {
-				put(ctxt, s, s.Name, UndefinedSym, s.Value)
-			}
-
-		case sym.SHOSTOBJ:
-			if !s.Attr.Reachable() {
-				continue
-			}
-			if ctxt.HeadType == objabi.Hwindows || ctxt.IsELF {
-				put(ctxt, s, s.Name, UndefinedSym, s.Value)
-			}
-
-		case sym.SDYNIMPORT:
-			if !s.Attr.Reachable() {
-				continue
-			}
-			put(ctxt, s, s.Extname(), UndefinedSym, 0)
-
-		case sym.STLSBSS:
-			if ctxt.LinkMode == LinkExternal {
-				put(ctxt, s, s.Name, TLSSym, Symaddr(s))
-			}
-		}
-	}
-
-	for _, s := range ctxt.Textp {
-		put(ctxt, s, s.Name, TextSym, s.Value)
-	}
-
-	if ctxt.Debugvlog != 0 || *flagN {
-		ctxt.Logf("symsize = %d\n", uint32(Symsize))
-	}
-}
-
-func Symaddr(s *sym.Symbol) int64 {
-	if !s.Attr.Reachable() {
-		Errorf(s, "unreachable symbol in symaddr")
-	}
-	return s.Value
-}
-
 func (ctxt *Link) xdefine(p string, t sym.SymKind, v int64) {
-	s := ctxt.Syms.Lookup(p, 0)
-	s.Type = t
-	s.Value = v
-	s.Attr |= sym.AttrReachable
-	s.Attr |= sym.AttrSpecial
-	s.Attr |= sym.AttrLocal
-}
-
-func (ctxt *Link) xdefine2(p string, t sym.SymKind, v int64) {
 	ldr := ctxt.loader
 	s := ldr.CreateSymForUpdate(p, 0)
 	s.SetType(t)
@@ -2674,14 +2386,14 @@
 	s.SetLocal(true)
 }
 
-func datoff(s *sym.Symbol, addr int64) int64 {
+func datoff(ldr *loader.Loader, s loader.Sym, addr int64) int64 {
 	if uint64(addr) >= Segdata.Vaddr {
 		return int64(uint64(addr) - Segdata.Vaddr + Segdata.Fileoff)
 	}
 	if uint64(addr) >= Segtext.Vaddr {
 		return int64(uint64(addr) - Segtext.Vaddr + Segtext.Fileoff)
 	}
-	Errorf(s, "invalid datoff %#x", addr)
+	ldr.Errorf(s, "invalid datoff %#x", addr)
 	return 0
 }
 
@@ -2690,57 +2402,16 @@
 	if a[0] >= '0' && a[0] <= '9' {
 		return atolwhex(a)
 	}
-	s := ctxt.Syms.Lookup(a, 0)
-	if s.Type == 0 {
+	ldr := ctxt.loader
+	s := ldr.Lookup(a, 0)
+	st := ldr.SymType(s)
+	if st == 0 {
 		return *FlagTextAddr
 	}
-	if ctxt.HeadType != objabi.Haix && s.Type != sym.STEXT {
-		Errorf(s, "entry not text")
+	if !ctxt.IsAIX() && st != sym.STEXT {
+		ldr.Errorf(s, "entry not text")
 	}
-	return s.Value
-}
-
-func undefsym(ctxt *Link, s *sym.Symbol) {
-	var r *sym.Reloc
-
-	for i := 0; i < len(s.R); i++ {
-		r = &s.R[i]
-		if r.Sym == nil { // happens for some external ARM relocs
-			continue
-		}
-		// TODO(mwhudson): the test of VisibilityHidden here probably doesn't make
-		// sense and should be removed when someone has thought about it properly.
-		if (r.Sym.Type == sym.Sxxx || r.Sym.Type == sym.SXREF) && !r.Sym.Attr.VisibilityHidden() {
-			Errorf(s, "undefined: %q", r.Sym.Name)
-		}
-		if !r.Sym.Attr.Reachable() && r.Type != objabi.R_WEAKADDROFF {
-			Errorf(s, "relocation target %q", r.Sym.Name)
-		}
-	}
-}
-
-func (ctxt *Link) undef() {
-	// undefsym performs checks (almost) identical to checks
-	// that report undefined relocations in relocsym.
-	// Both undefsym and relocsym can report same symbol as undefined,
-	// which results in error message duplication (see #10978).
-	//
-	// The undef is run after Arch.Asmb and could detect some
-	// programming errors there, but if object being linked is already
-	// failed with errors, it is better to avoid duplicated errors.
-	if nerrors > 0 {
-		return
-	}
-
-	for _, s := range ctxt.Textp {
-		undefsym(ctxt, s)
-	}
-	for _, s := range ctxt.datap {
-		undefsym(ctxt, s)
-	}
-	if nerrors > 0 {
-		errorexit()
-	}
+	return ldr.SymValue(s)
 }
 
 func (ctxt *Link) callgraph() {
@@ -2749,7 +2420,7 @@
 	}
 
 	ldr := ctxt.loader
-	for _, s := range ctxt.Textp2 {
+	for _, s := range ctxt.Textp {
 		relocs := ldr.Relocs(s)
 		for i := 0; i < relocs.Count(); i++ {
 			r := relocs.At2(i)
@@ -2819,143 +2490,42 @@
 	*order = append(*order, lib)
 }
 
-// addToTextp populates the context Textp slice.
-func addToTextp(ctxt *Link) {
-	// Set up ctxt.Textp, based on ctxt.Textp2.
-	textp := make([]*sym.Symbol, 0, len(ctxt.Textp2))
-	haveshlibs := len(ctxt.Shlibs) > 0
-	for _, tsym := range ctxt.Textp2 {
-		sp := ctxt.loader.Syms[tsym]
-		if sp == nil || !ctxt.loader.AttrReachable(tsym) {
-			panic("should never happen")
-		}
-		if haveshlibs && sp.Type == sym.SDYNIMPORT {
-			continue
-		}
-		textp = append(textp, sp)
-	}
-	ctxt.Textp = textp
-}
-
-func (ctxt *Link) loadlibfull(symGroupType []sym.SymKind, needReloc, needExtReloc bool) {
-	// Load full symbol contents, resolve indexed references.
-	ctxt.loader.LoadFull(ctxt.Arch, ctxt.Syms, needReloc, needExtReloc)
-
-	// Convert ctxt.Moduledata2 to ctxt.Moduledata, etc
-	if ctxt.Moduledata2 != 0 {
-		ctxt.Moduledata = ctxt.loader.Syms[ctxt.Moduledata2]
-		ctxt.Tlsg = ctxt.loader.Syms[ctxt.Tlsg2]
-	}
-
-	// Pull the symbols out.
-	ctxt.loader.ExtractSymbols(ctxt.Syms)
-	ctxt.lookup = ctxt.Syms.ROLookup
-
-	// Recreate dynexp using *sym.Symbol instead of loader.Sym
-	genSymsForDynexp(ctxt)
-
-	// Drop the cgodata reference.
-	ctxt.cgodata = nil
-
-	addToTextp(ctxt)
-
-	// Set special global symbols.
-	ctxt.setArchSyms(AfterLoadlibFull)
-
-	// Populate dwarfp from dwarfp2. If we see a symbol index
-	// whose loader.Syms entry is nil, something went wrong.
-	for _, si := range dwarfp2 {
-		syms := make([]*sym.Symbol, 0, len(si.syms))
-		for _, symIdx := range si.syms {
-			s := ctxt.loader.Syms[symIdx]
-			if s == nil {
-				panic(fmt.Sprintf("nil sym for dwarfp2 element %d", symIdx))
-			}
-			s.Attr |= sym.AttrLocal
-			syms = append(syms, s)
-		}
-		dwarfp = append(dwarfp, dwarfSecInfo2{syms: syms})
-	}
-
-	// Populate datap from datap2
-	ctxt.datap = make([]*sym.Symbol, len(ctxt.datap2))
-	for i, symIdx := range ctxt.datap2 {
-		s := ctxt.loader.Syms[symIdx]
-		if s == nil {
-			panic(fmt.Sprintf("nil sym for datap2 element %d", symIdx))
-		}
-		ctxt.datap[i] = s
-	}
-
-	// Populate the sym.Section 'Sym' fields based on their 'Sym2'
-	// fields.
-	allSegments := []*sym.Segment{&Segtext, &Segrodata, &Segrelrodata, &Segdata, &Segdwarf}
-	for _, seg := range allSegments {
-		for _, sect := range seg.Sections {
-			if sect.Sym2 != 0 {
-				s := ctxt.loader.Syms[sect.Sym2]
-				if s == nil {
-					panic(fmt.Sprintf("nil sym for sect %s sym %d", sect.Name, sect.Sym2))
-				}
-				sect.Sym = s
-			}
-		}
-	}
-
-	// For now, overwrite symbol type with its "group" type, as dodata
-	// expected. Once we converted dodata, this will probably not be
-	// needed.
-	for i, t := range symGroupType {
-		if t != sym.Sxxx {
-			s := ctxt.loader.Syms[i]
-			if s == nil {
-				continue // in dwarfcompress we drop compressed DWARF symbols
-			}
-			s.Type = t
-		}
-	}
-	symGroupType = nil
-
-	if ctxt.Debugvlog > 1 {
-		// loadlibfull is likely a good place to dump.
-		// Only dump under -v=2 and above.
-		ctxt.dumpsyms()
-	}
-}
-
-func symPkg(ctxt *Link, s *sym.Symbol) string {
-	if s == nil {
-		return ""
-	}
-	return ctxt.loader.SymPkg(loader.Sym(s.SymIdx))
-}
-
-func ElfSymForReloc(ctxt *Link, s *sym.Symbol) int32 {
+func ElfSymForReloc(ctxt *Link, s loader.Sym) int32 {
 	// If putelfsym created a local version of this symbol, use that in all
 	// relocations.
-	les := ctxt.loader.SymLocalElfSym(loader.Sym(s.SymIdx))
+	les := ctxt.loader.SymLocalElfSym(s)
 	if les != 0 {
 		return les
 	} else {
-		return ctxt.loader.SymElfSym(loader.Sym(s.SymIdx))
+		return ctxt.loader.SymElfSym(s)
 	}
 }
 
-func symSub(ctxt *Link, s *sym.Symbol) *sym.Symbol {
-	if lsub := ctxt.loader.SubSym(loader.Sym(s.SymIdx)); lsub != 0 {
-		return ctxt.loader.Syms[lsub]
+func AddGotSym(target *Target, ldr *loader.Loader, syms *ArchSyms, s loader.Sym, elfRelocTyp uint32) {
+	if ldr.SymGot(s) >= 0 {
+		return
 	}
-	return nil
-}
 
-func (ctxt *Link) dumpsyms() {
-	for _, s := range ctxt.loader.Syms {
-		if s == nil {
-			continue
+	Adddynsym(ldr, target, syms, s)
+	got := ldr.MakeSymbolUpdater(syms.GOT)
+	ldr.SetGot(s, int32(got.Size()))
+	got.AddUint(target.Arch, 0)
+
+	if target.IsElf() {
+		if target.Arch.PtrSize == 8 {
+			rela := ldr.MakeSymbolUpdater(syms.Rela)
+			rela.AddAddrPlus(target.Arch, got.Sym(), int64(ldr.SymGot(s)))
+			rela.AddUint64(target.Arch, ELF64_R_INFO(uint32(ldr.SymDynid(s)), elfRelocTyp))
+			rela.AddUint64(target.Arch, 0)
+		} else {
+			rel := ldr.MakeSymbolUpdater(syms.Rel)
+			rel.AddAddrPlus(target.Arch, got.Sym(), int64(ldr.SymGot(s)))
+			rel.AddUint32(target.Arch, ELF32_R_INFO(uint32(ldr.SymDynid(s)), elfRelocTyp))
 		}
-		fmt.Printf("%s %s reachable=%v onlist=%v outer=%v sub=%v\n", s, s.Type, s.Attr.Reachable(), s.Attr.OnList(), s.Outer, symSub(ctxt, s))
-		for i := range s.R {
-			fmt.Println("\t", s.R[i].Type, s.R[i].Sym)
-		}
+	} else if target.IsDarwin() {
+		leg := ldr.MakeSymbolUpdater(syms.LinkEditGOT)
+		leg.AddUint32(target.Arch, uint32(ldr.SymDynid(s)))
+	} else {
+		ldr.Errorf(s, "addgotsym: unsupported binary format")
 	}
 }
diff --git a/src/cmd/link/internal/ld/link.go b/src/cmd/link/internal/ld/link.go
index 435b608..9ad477e 100644
--- a/src/cmd/link/internal/ld/link.go
+++ b/src/cmd/link/internal/ld/link.go
@@ -57,7 +57,7 @@
 	outSem chan int // limits the number of output writers
 	Out    *OutBuf
 
-	Syms *sym.Symbols
+	version int // current version number for static/file-local symbols
 
 	Debugvlog int
 	Bso       *bufio.Writer
@@ -70,11 +70,9 @@
 	Library      []*sym.Library
 	LibraryByPkg map[string]*sym.Library
 	Shlibs       []Shlib
-	Textp        []*sym.Symbol
-	Textp2       []loader.Sym
+	Textp        []loader.Sym
 	NumFilesyms  int
-	Moduledata   *sym.Symbol
-	Moduledata2  loader.Sym
+	Moduledata   loader.Sym
 
 	PackageFile  map[string]string
 	PackageShlib map[string]string
@@ -90,13 +88,11 @@
 	cgo_export_static  map[string]bool
 	cgo_export_dynamic map[string]bool
 
-	datap   []*sym.Symbol
-	datap2  []loader.Sym
-	dynexp2 []loader.Sym
+	datap  []loader.Sym
+	dynexp []loader.Sym
 
 	// Elf symtab variables.
 	numelfsym int // starts at 0, 1 is reserved
-	elfbind   int
 }
 
 type cgodata struct {
@@ -137,3 +133,14 @@
 	}
 	l.Autolib = nil
 }
+
+// Allocate a new version (i.e. symbol namespace).
+func (ctxt *Link) IncVersion() int {
+	ctxt.version++
+	return ctxt.version - 1
+}
+
+// returns the maximum version number
+func (ctxt *Link) MaxVersion() int {
+	return ctxt.version
+}
diff --git a/src/cmd/link/internal/ld/macho.go b/src/cmd/link/internal/ld/macho.go
index 5548b8c..c8f02c4 100644
--- a/src/cmd/link/internal/ld/macho.go
+++ b/src/cmd/link/internal/ld/macho.go
@@ -501,9 +501,8 @@
 
 	var msect *MachoSect
 	if sect.Rwx&1 == 0 && segname != "__DWARF" && (ctxt.Arch.Family == sys.ARM64 ||
-		ctxt.Arch.Family == sys.ARM ||
 		(ctxt.Arch.Family == sys.AMD64 && ctxt.BuildMode != BuildModeExe)) {
-		// Darwin external linker on arm and arm64, and on amd64 in c-shared/c-archive buildmode
+		// Darwin external linker on arm64, and on amd64 in c-shared/c-archive buildmode
 		// complains about absolute relocs in __TEXT, so if the section is not
 		// executable, put it in __DATA segment.
 		msect = newMachoSect(mseg, buf, "__DATA")
@@ -551,7 +550,7 @@
 	if sect.Name == ".got" {
 		msect.name = "__nl_symbol_ptr"
 		msect.flag = S_NON_LAZY_SYMBOL_POINTERS
-		msect.res1 = uint32(ctxt.Syms.Lookup(".linkedit.plt", 0).Size / 4) /* offset into indirect symbol table */
+		msect.res1 = uint32(ctxt.loader.SymSize(ctxt.ArchSyms.LinkEditPLT) / 4) /* offset into indirect symbol table */
 	}
 
 	if sect.Name == ".init_array" {
@@ -575,7 +574,15 @@
 	}
 }
 
-func Asmbmacho(ctxt *Link) {
+func asmbMacho(ctxt *Link) {
+	machlink := doMachoLink(ctxt)
+	if !*FlagS && ctxt.IsExternal() {
+		symo := int64(Segdwarf.Fileoff + uint64(Rnd(int64(Segdwarf.Filelen), int64(*FlagRound))) + uint64(machlink))
+		ctxt.Out.SeekSet(symo)
+		machoEmitReloc(ctxt)
+	}
+	ctxt.Out.SeekSet(0)
+
 	/* apple MACH */
 	va := *FlagTextAddr - int64(HEADR)
 
@@ -584,10 +591,6 @@
 	default:
 		Exitf("unknown macho architecture: %v", ctxt.Arch.Family)
 
-	case sys.ARM:
-		mh.cpu = MACHO_CPU_ARM
-		mh.subcpu = MACHO_SUBCPU_ARMV7
-
 	case sys.AMD64:
 		mh.cpu = MACHO_CPU_AMD64
 		mh.subcpu = MACHO_SUBCPU_X86
@@ -595,10 +598,6 @@
 	case sys.ARM64:
 		mh.cpu = MACHO_CPU_ARM64
 		mh.subcpu = MACHO_SUBCPU_ARM64_ALL
-
-	case sys.I386:
-		mh.cpu = MACHO_CPU_386
-		mh.subcpu = MACHO_SUBCPU_X86
 	}
 
 	var ms *MachoSeg
@@ -669,12 +668,6 @@
 		default:
 			Exitf("unknown macho architecture: %v", ctxt.Arch.Family)
 
-		case sys.ARM:
-			ml := newMachoLoad(ctxt.Arch, LC_UNIXTHREAD, 17+2)
-			ml.data[0] = 1                           /* thread type */
-			ml.data[1] = 17                          /* word count */
-			ml.data[2+15] = uint32(Entryvalue(ctxt)) /* start pc */
-
 		case sys.AMD64:
 			ml := newMachoLoad(ctxt.Arch, LC_UNIXTHREAD, 42+2)
 			ml.data[0] = 4                           /* thread type */
@@ -688,26 +681,22 @@
 			ml.data[1] = 68                          /* word count */
 			ml.data[2+64] = uint32(Entryvalue(ctxt)) /* start pc */
 			ml.data[2+64+1] = uint32(Entryvalue(ctxt) >> 32)
-
-		case sys.I386:
-			ml := newMachoLoad(ctxt.Arch, LC_UNIXTHREAD, 16+2)
-			ml.data[0] = 1                           /* thread type */
-			ml.data[1] = 16                          /* word count */
-			ml.data[2+10] = uint32(Entryvalue(ctxt)) /* start pc */
 		}
 	}
 
 	if !*FlagD {
+		ldr := ctxt.loader
+
 		// must match domacholink below
-		s1 := ctxt.Syms.Lookup(".machosymtab", 0)
-		s2 := ctxt.Syms.Lookup(".linkedit.plt", 0)
-		s3 := ctxt.Syms.Lookup(".linkedit.got", 0)
-		s4 := ctxt.Syms.Lookup(".machosymstr", 0)
+		s1 := ldr.SymSize(ldr.Lookup(".machosymtab", 0))
+		s2 := ldr.SymSize(ctxt.ArchSyms.LinkEditPLT)
+		s3 := ldr.SymSize(ctxt.ArchSyms.LinkEditGOT)
+		s4 := ldr.SymSize(ldr.Lookup(".machosymstr", 0))
 
 		if ctxt.LinkMode != LinkExternal {
 			ms := newMachoSeg("__LINKEDIT", 0)
 			ms.vaddr = uint64(va) + uint64(v) + uint64(Rnd(int64(Segdata.Length), int64(*FlagRound)))
-			ms.vsize = uint64(s1.Size) + uint64(s2.Size) + uint64(s3.Size) + uint64(s4.Size)
+			ms.vsize = uint64(s1) + uint64(s2) + uint64(s3) + uint64(s4)
 			ms.fileoffset = uint64(linkoff)
 			ms.filesize = ms.vsize
 			ms.prot1 = 7
@@ -715,10 +704,10 @@
 		}
 
 		ml := newMachoLoad(ctxt.Arch, LC_SYMTAB, 4)
-		ml.data[0] = uint32(linkoff)                               /* symoff */
-		ml.data[1] = uint32(nsortsym)                              /* nsyms */
-		ml.data[2] = uint32(linkoff + s1.Size + s2.Size + s3.Size) /* stroff */
-		ml.data[3] = uint32(s4.Size)                               /* strsize */
+		ml.data[0] = uint32(linkoff)                /* symoff */
+		ml.data[1] = uint32(nsortsym)               /* nsyms */
+		ml.data[2] = uint32(linkoff + s1 + s2 + s3) /* stroff */
+		ml.data[3] = uint32(s4)                     /* strsize */
 
 		machodysymtab(ctxt)
 
@@ -777,7 +766,7 @@
 	}
 
 	// Add text symbols.
-	for _, s := range ctxt.Textp2 {
+	for _, s := range ctxt.Textp {
 		addsym(s)
 	}
 
@@ -798,7 +787,7 @@
 			continue
 		}
 		t := ldr.SymType(s)
-		if t >= sym.SELFRXSECT && t < sym.SXREF || t == sym.SCONST { // data sections handled in dodata
+		if t >= sym.SELFRXSECT && t < sym.SXREF { // data sections handled in dodata
 			if t == sym.STLSBSS {
 				// TLSBSS is not used on darwin. See data.go:allocateDataSections
 				continue
@@ -845,7 +834,7 @@
 	// On Mac OS X Mountain Lion, we must sort exported symbols
 	// So we sort them here and pre-allocate dynid for them
 	// See https://golang.org/issue/4029
-	for _, s := range ctxt.dynexp2 {
+	for _, s := range ctxt.dynexp {
 		if !ldr.AttrReachable(s) {
 			panic("dynexp symbol is not reachable")
 		}
@@ -870,38 +859,39 @@
 //
 // When dynamically linking, all non-local variables and plugin-exported
 // symbols need to be exported.
-func machoShouldExport(ctxt *Link, s *sym.Symbol) bool {
-	if !ctxt.DynlinkingGo() || s.Attr.Local() {
+func machoShouldExport(ctxt *Link, ldr *loader.Loader, s loader.Sym) bool {
+	if !ctxt.DynlinkingGo() || ldr.AttrLocal(s) {
 		return false
 	}
-	if ctxt.BuildMode == BuildModePlugin && strings.HasPrefix(s.Extname(), objabi.PathToPrefix(*flagPluginPath)) {
+	if ctxt.BuildMode == BuildModePlugin && strings.HasPrefix(ldr.SymExtname(s), objabi.PathToPrefix(*flagPluginPath)) {
 		return true
 	}
-	if strings.HasPrefix(s.Name, "go.itab.") {
+	name := ldr.RawSymName(s)
+	if strings.HasPrefix(name, "go.itab.") {
 		return true
 	}
-	if strings.HasPrefix(s.Name, "type.") && !strings.HasPrefix(s.Name, "type..") {
+	if strings.HasPrefix(name, "type.") && !strings.HasPrefix(name, "type..") {
 		// reduce runtime typemap pressure, but do not
 		// export alg functions (type..*), as these
 		// appear in pclntable.
 		return true
 	}
-	if strings.HasPrefix(s.Name, "go.link.pkghash") {
+	if strings.HasPrefix(name, "go.link.pkghash") {
 		return true
 	}
-	return s.Type >= sym.SFirstWritable // only writable sections
+	return ldr.SymType(s) >= sym.SFirstWritable // only writable sections
 }
 
 func machosymtab(ctxt *Link) {
-	symtab := ctxt.Syms.Lookup(".machosymtab", 0)
-	symstr := ctxt.Syms.Lookup(".machosymstr", 0)
+	ldr := ctxt.loader
+	symtab := ldr.CreateSymForUpdate(".machosymtab", 0)
+	symstr := ldr.CreateSymForUpdate(".machosymstr", 0)
 
-	for i := 0; i < nsortsym; i++ {
-		s := ctxt.loader.Syms[sortsym[i]]
-		symtab.AddUint32(ctxt.Arch, uint32(symstr.Size))
+	for _, s := range sortsym[:nsortsym] {
+		symtab.AddUint32(ctxt.Arch, uint32(symstr.Size()))
 
-		export := machoShouldExport(ctxt, s)
-		isGoSymbol := strings.Contains(s.Extname(), ".")
+		export := machoShouldExport(ctxt, ldr, s)
+		isGoSymbol := strings.Contains(ldr.SymExtname(s), ".")
 
 		// In normal buildmodes, only add _ to C symbols, as
 		// Go symbols have dot in the name.
@@ -910,37 +900,37 @@
 		// symbols like crosscall2 are in pclntab and end up
 		// pointing at the host binary, breaking unwinding.
 		// See Issue #18190.
-		cexport := !isGoSymbol && (ctxt.BuildMode != BuildModePlugin || onlycsymbol(s.Name))
+		cexport := !isGoSymbol && (ctxt.BuildMode != BuildModePlugin || onlycsymbol(ldr.SymName(s)))
 		if cexport || export || isGoSymbol {
 			symstr.AddUint8('_')
 		}
 
 		// replace "·" as ".", because DTrace cannot handle it.
-		Addstring(symstr, strings.Replace(s.Extname(), "·", ".", -1))
+		symstr.Addstring(strings.Replace(ldr.SymExtname(s), "·", ".", -1))
 
-		if s.Type == sym.SDYNIMPORT || s.Type == sym.SHOSTOBJ || s.Type == sym.SUNDEFEXT {
+		if t := ldr.SymType(s); t == sym.SDYNIMPORT || t == sym.SHOSTOBJ || t == sym.SUNDEFEXT {
 			symtab.AddUint8(0x01)                             // type N_EXT, external symbol
 			symtab.AddUint8(0)                                // no section
 			symtab.AddUint16(ctxt.Arch, 0)                    // desc
 			symtab.AddUintXX(ctxt.Arch, 0, ctxt.Arch.PtrSize) // no value
 		} else {
-			if s.Attr.CgoExport() || export {
+			if ldr.AttrCgoExport(s) || export {
 				symtab.AddUint8(0x0f)
 			} else {
 				symtab.AddUint8(0x0e)
 			}
 			o := s
-			for o.Outer != nil {
-				o = o.Outer
+			if outer := ldr.OuterSym(o); outer != 0 {
+				o = outer
 			}
-			if o.Sect == nil {
-				Errorf(s, "missing section for symbol")
+			if ldr.SymSect(o) == nil {
+				ldr.Errorf(s, "missing section for symbol")
 				symtab.AddUint8(0)
 			} else {
-				symtab.AddUint8(uint8(o.Sect.Extnum))
+				symtab.AddUint8(uint8(ldr.SymSect(o).Extnum))
 			}
 			symtab.AddUint16(ctxt.Arch, 0) // desc
-			symtab.AddUintXX(ctxt.Arch, uint64(Symaddr(s)), ctxt.Arch.PtrSize)
+			symtab.AddUintXX(ctxt.Arch, uint64(ldr.SymAddr(s)), ctxt.Arch.PtrSize)
 		}
 	}
 }
@@ -967,13 +957,14 @@
 	ml.data[10] = 0 /* extrefsymoff */
 	ml.data[11] = 0 /* nextrefsyms */
 
-	// must match domacholink below
-	s1 := ctxt.Syms.Lookup(".machosymtab", 0)
+	ldr := ctxt.loader
 
-	s2 := ctxt.Syms.Lookup(".linkedit.plt", 0)
-	s3 := ctxt.Syms.Lookup(".linkedit.got", 0)
-	ml.data[12] = uint32(linkoff + s1.Size)       /* indirectsymoff */
-	ml.data[13] = uint32((s2.Size + s3.Size) / 4) /* nindirectsyms */
+	// must match domacholink below
+	s1 := ldr.SymSize(ldr.Lookup(".machosymtab", 0))
+	s2 := ldr.SymSize(ctxt.ArchSyms.LinkEditPLT)
+	s3 := ldr.SymSize(ctxt.ArchSyms.LinkEditGOT)
+	ml.data[12] = uint32(linkoff + s1)  /* indirectsymoff */
+	ml.data[13] = uint32((s2 + s3) / 4) /* nindirectsyms */
 
 	ml.data[14] = 0 /* extreloff */
 	ml.data[15] = 0 /* nextrel */
@@ -981,15 +972,16 @@
 	ml.data[17] = 0 /* nlocrel */
 }
 
-func Domacholink(ctxt *Link) int64 {
+func doMachoLink(ctxt *Link) int64 {
 	machosymtab(ctxt)
 
-	// write data that will be linkedit section
-	s1 := ctxt.Syms.Lookup(".machosymtab", 0)
+	ldr := ctxt.loader
 
-	s2 := ctxt.Syms.Lookup(".linkedit.plt", 0)
-	s3 := ctxt.Syms.Lookup(".linkedit.got", 0)
-	s4 := ctxt.Syms.Lookup(".machosymstr", 0)
+	// write data that will be linkedit section
+	s1 := ldr.Lookup(".machosymtab", 0)
+	s2 := ctxt.ArchSyms.LinkEditPLT
+	s3 := ctxt.ArchSyms.LinkEditGOT
+	s4 := ldr.Lookup(".machosymstr", 0)
 
 	// Force the linkedit section to end on a 16-byte
 	// boundary. This allows pure (non-cgo) Go binaries
@@ -1008,26 +1000,27 @@
 	// boundary, codesign_allocate will not need to apply
 	// any alignment padding itself, working around the
 	// issue.
-	for s4.Size%16 != 0 {
-		s4.AddUint8(0)
+	s4b := ldr.MakeSymbolUpdater(s4)
+	for s4b.Size()%16 != 0 {
+		s4b.AddUint8(0)
 	}
 
-	size := int(s1.Size + s2.Size + s3.Size + s4.Size)
+	size := int(ldr.SymSize(s1) + ldr.SymSize(s2) + ldr.SymSize(s3) + ldr.SymSize(s4))
 
 	if size > 0 {
 		linkoff = Rnd(int64(uint64(HEADR)+Segtext.Length), int64(*FlagRound)) + Rnd(int64(Segdata.Filelen), int64(*FlagRound)) + Rnd(int64(Segdwarf.Filelen), int64(*FlagRound))
 		ctxt.Out.SeekSet(linkoff)
 
-		ctxt.Out.Write(s1.P[:s1.Size])
-		ctxt.Out.Write(s2.P[:s2.Size])
-		ctxt.Out.Write(s3.P[:s3.Size])
-		ctxt.Out.Write(s4.P[:s4.Size])
+		ctxt.Out.Write(ldr.Data(s1))
+		ctxt.Out.Write(ldr.Data(s2))
+		ctxt.Out.Write(ldr.Data(s3))
+		ctxt.Out.Write(ldr.Data(s4))
 	}
 
 	return Rnd(int64(size), int64(*FlagRound))
 }
 
-func machorelocsect(ctxt *Link, sect *sym.Section, syms []*sym.Symbol) {
+func machorelocsect(ctxt *Link, ldr *loader.Loader, sect *sym.Section, syms []loader.Sym) {
 	// If main section has no bits, nothing to relocate.
 	if sect.Vaddr >= sect.Seg.Vaddr+sect.Seg.Filelen {
 		return
@@ -1035,10 +1028,10 @@
 
 	sect.Reloff = uint64(ctxt.Out.Offset())
 	for i, s := range syms {
-		if !s.Attr.Reachable() {
+		if !ldr.AttrReachable(s) {
 			continue
 		}
-		if uint64(s.Value) >= sect.Vaddr {
+		if uint64(ldr.SymValue(s)) >= sect.Vaddr {
 			syms = syms[i:]
 			break
 		}
@@ -1046,26 +1039,24 @@
 
 	eaddr := int32(sect.Vaddr + sect.Length)
 	for _, s := range syms {
-		if !s.Attr.Reachable() {
+		if !ldr.AttrReachable(s) {
 			continue
 		}
-		if s.Value >= int64(eaddr) {
+		if ldr.SymValue(s) >= int64(eaddr) {
 			break
 		}
-		for ri := range s.R {
-			r := &s.R[ri]
-			if r.Done {
+		relocs := ldr.ExtRelocs(s)
+		for ri := 0; ri < relocs.Count(); ri++ {
+			r := relocs.At(ri)
+			if r.Xsym == 0 {
+				ldr.Errorf(s, "missing xsym in relocation")
 				continue
 			}
-			if r.Xsym == nil {
-				Errorf(s, "missing xsym in relocation")
-				continue
+			if !ldr.AttrReachable(r.Xsym) {
+				ldr.Errorf(s, "unreachable reloc %d (%s) target %v", r.Type(), sym.RelocName(ctxt.Arch, r.Type()), ldr.SymName(r.Xsym))
 			}
-			if !r.Xsym.Attr.Reachable() {
-				Errorf(s, "unreachable reloc %d (%s) target %v", r.Type, sym.RelocName(ctxt.Arch, r.Type), r.Xsym.Name)
-			}
-			if !thearch.Machoreloc1(ctxt.Arch, ctxt.Out, s, r, int64(uint64(s.Value+int64(r.Off))-sect.Vaddr)) {
-				Errorf(s, "unsupported obj reloc %d (%s)/%d to %s", r.Type, sym.RelocName(ctxt.Arch, r.Type), r.Siz, r.Sym.Name)
+			if !thearch.Machoreloc1(ctxt.Arch, ctxt.Out, ldr, s, r, int64(uint64(ldr.SymValue(s)+int64(r.Off()))-sect.Vaddr)) {
+				ldr.Errorf(s, "unsupported obj reloc %d (%s)/%d to %s", r.Type(), sym.RelocName(ctxt.Arch, r.Type()), r.Siz(), ldr.SymName(r.Sym()))
 			}
 		}
 	}
@@ -1073,26 +1064,27 @@
 	sect.Rellen = uint64(ctxt.Out.Offset()) - sect.Reloff
 }
 
-func Machoemitreloc(ctxt *Link) {
+func machoEmitReloc(ctxt *Link) {
 	for ctxt.Out.Offset()&7 != 0 {
 		ctxt.Out.Write8(0)
 	}
 
-	machorelocsect(ctxt, Segtext.Sections[0], ctxt.Textp)
+	ldr := ctxt.loader
+	machorelocsect(ctxt, ldr, Segtext.Sections[0], ctxt.Textp)
 	for _, sect := range Segtext.Sections[1:] {
-		machorelocsect(ctxt, sect, ctxt.datap)
+		machorelocsect(ctxt, ldr, sect, ctxt.datap)
 	}
 	for _, sect := range Segdata.Sections {
-		machorelocsect(ctxt, sect, ctxt.datap)
+		machorelocsect(ctxt, ldr, sect, ctxt.datap)
 	}
 	for i := 0; i < len(Segdwarf.Sections); i++ {
 		sect := Segdwarf.Sections[i]
 		si := dwarfp[i]
-		if si.secSym() != sect.Sym ||
-			si.secSym().Sect != sect {
+		if si.secSym() != loader.Sym(sect.Sym) ||
+			ctxt.loader.SymSect(si.secSym()) != sect {
 			panic("inconsistency between dwarfp and Segdwarf")
 		}
-		machorelocsect(ctxt, sect, si.syms)
+		machorelocsect(ctxt, ldr, sect, si.syms)
 	}
 }
 
diff --git a/src/cmd/link/internal/ld/main.go b/src/cmd/link/internal/ld/main.go
index 2738c8a..e68997f 100644
--- a/src/cmd/link/internal/ld/main.go
+++ b/src/cmd/link/internal/ld/main.go
@@ -39,7 +39,6 @@
 	"flag"
 	"log"
 	"os"
-	"os/exec"
 	"runtime"
 	"runtime/pprof"
 	"strings"
@@ -83,9 +82,8 @@
 	flagH           = flag.Bool("h", false, "halt on error")
 	flagN           = flag.Bool("n", false, "dump symbol table")
 	FlagS           = flag.Bool("s", false, "disable symbol table")
-	flagU           = flag.Bool("u", false, "reject unsafe packages")
 	FlagW           = flag.Bool("w", false, "disable DWARF generation")
-	Flag8           bool // use 64-bit addresses in symbol table
+	flag8           bool // use 64-bit addresses in symbol table
 	flagInterpreter = flag.String("I", "", "use `linker` as ELF dynamic linker")
 	FlagDebugTramp  = flag.Int("debugtramp", 0, "debug trampolines")
 	FlagStrictDups  = flag.Int("strictdups", 0, "sanity check duplicate symbol contents during object file reading (1=warn 2=err).")
@@ -99,8 +97,6 @@
 
 	benchmarkFlag     = flag.String("benchmark", "", "set to 'mem' or 'cpu' to enable phase benchmarking")
 	benchmarkFileFlag = flag.String("benchmarkprofile", "", "emit phase profiles to `base`_phase.{cpu,mem}prof")
-
-	flagGo115Newobj = flag.Bool("go115newobj", true, "use new object file format")
 )
 
 // Main is the main entry point for the linker code.
@@ -124,7 +120,7 @@
 
 	// TODO(matloob): define these above and then check flag values here
 	if ctxt.Arch.Family == sys.AMD64 && objabi.GOOS == "plan9" {
-		flag.BoolVar(&Flag8, "8", false, "use 64-bit addresses in symbol table")
+		flag.BoolVar(&flag8, "8", false, "use 64-bit addresses in symbol table")
 	}
 	flagHeadType := flag.String("H", "", "set header `type`")
 	flag.BoolVar(&ctxt.linkShared, "linkshared", false, "link against installed Go shared libraries")
@@ -140,10 +136,6 @@
 
 	objabi.Flagparse(usage)
 
-	if !*flagGo115Newobj {
-		oldlink()
-	}
-
 	switch *flagHeadType {
 	case "":
 	case "windowsgui":
@@ -279,10 +271,10 @@
 	ctxt.textbuildid()
 	bench.Start("addexport")
 	setupdynexp(ctxt)
-	ctxt.setArchSyms(BeforeLoadlibFull)
+	ctxt.setArchSyms()
 	ctxt.addexport()
 	bench.Start("Gentext")
-	thearch.Gentext2(ctxt, ctxt.loader) // trampolines, call stubs, etc.
+	thearch.Gentext(ctxt, ctxt.loader) // trampolines, call stubs, etc.
 
 	bench.Start("textaddress")
 	ctxt.textaddress()
@@ -299,7 +291,7 @@
 	bench.Start("symtab")
 	symGroupType := ctxt.symtab()
 	bench.Start("dodata")
-	ctxt.dodata2(symGroupType)
+	ctxt.dodata(symGroupType)
 	bench.Start("address")
 	order := ctxt.address()
 	bench.Start("dwarfcompress")
@@ -320,43 +312,23 @@
 			panic(err)
 		}
 	}
-	// Asmb will redirect symbols to the output file mmap, and relocations
+	// asmb will redirect symbols to the output file mmap, and relocations
 	// will be applied directly there.
 	bench.Start("Asmb")
 	ctxt.loader.InitOutData()
-	thearch.Asmb(ctxt, ctxt.loader)
-
-	newreloc := ctxt.IsAMD64() || ctxt.Is386() || ctxt.IsWasm()
-	if newreloc {
-		bench.Start("reloc")
-		ctxt.reloc()
-		bench.Start("loadlibfull")
-		// We don't need relocations at this point.
-		// An exception is internal linking on Windows, see pe.go:addPEBaseRelocSym
-		// Wasm is another exception, where it applies text relocations in Asmb2.
-		needReloc := (ctxt.IsWindows() && ctxt.IsInternal()) || ctxt.IsWasm()
-		// On AMD64 ELF, we directly use the loader's ExtRelocs, so we don't
-		// need conversion. Otherwise we do.
-		needExtReloc := ctxt.IsExternal() && !(ctxt.IsAMD64() && ctxt.IsELF)
-		ctxt.loadlibfull(symGroupType, needReloc, needExtReloc) // XXX do it here for now
-	} else {
-		bench.Start("loadlibfull")
-		ctxt.loadlibfull(symGroupType, true, false) // XXX do it here for now
-		bench.Start("reloc")
-		ctxt.reloc2()
-	}
+	asmb(ctxt, ctxt.loader)
+	bench.Start("reloc")
+	ctxt.reloc()
 	bench.Start("Asmb2")
-	thearch.Asmb2(ctxt)
+	asmb2(ctxt)
 
 	bench.Start("Munmap")
 	ctxt.Out.Close() // Close handles Munmapping if necessary.
 
-	bench.Start("undef")
-	ctxt.undef()
 	bench.Start("hostlink")
 	ctxt.hostlink()
 	if ctxt.Debugvlog != 0 {
-		ctxt.Logf("%d symbols, %d reachable\n", len(ctxt.loader.Syms), ctxt.loader.NReachableSym())
+		ctxt.Logf("%d symbols, %d reachable\n", ctxt.loader.NSym(), ctxt.loader.NReachableSym())
 		ctxt.Logf("%d liveness data\n", liveness)
 	}
 	bench.Start("Flush")
@@ -415,48 +387,3 @@
 		})
 	}
 }
-
-// Invoke the old linker and exit.
-func oldlink() {
-	linker := os.Args[0]
-	if strings.HasSuffix(linker, "link") {
-		linker = linker[:len(linker)-4] + "oldlink"
-	} else if strings.HasSuffix(linker, "link.exe") {
-		linker = linker[:len(linker)-8] + "oldlink.exe"
-	} else {
-		log.Fatal("cannot find oldlink. arg0=", linker)
-	}
-
-	// Copy args, filter out -go115newobj flag
-	args := make([]string, 0, len(os.Args)-1)
-	skipNext := false
-	for i, a := range os.Args {
-		if i == 0 {
-			continue // skip arg0
-		}
-		if skipNext {
-			skipNext = false
-			continue
-		}
-		if a == "-go115newobj" {
-			skipNext = true
-			continue
-		}
-		if strings.HasPrefix(a, "-go115newobj=") {
-			continue
-		}
-		args = append(args, a)
-	}
-
-	cmd := exec.Command(linker, args...)
-	cmd.Stdout = os.Stdout
-	cmd.Stderr = os.Stderr
-	err := cmd.Run()
-	if err == nil {
-		os.Exit(0)
-	}
-	if _, ok := err.(*exec.ExitError); ok {
-		os.Exit(2) // would be nice to use ExitError.ExitCode(), but that is too new
-	}
-	log.Fatal("invoke oldlink failed:", err)
-}
diff --git a/src/cmd/link/internal/ld/outbuf_mmap.go b/src/cmd/link/internal/ld/outbuf_mmap.go
index e2e50cc84..41c436e 100644
--- a/src/cmd/link/internal/ld/outbuf_mmap.go
+++ b/src/cmd/link/internal/ld/outbuf_mmap.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin dragonfly freebsd linux openbsd
+// +build aix darwin dragonfly freebsd linux netbsd openbsd
 
 package ld
 
diff --git a/src/cmd/link/internal/ld/outbuf_nommap.go b/src/cmd/link/internal/ld/outbuf_nommap.go
index 51218d8..bad01dc 100644
--- a/src/cmd/link/internal/ld/outbuf_nommap.go
+++ b/src/cmd/link/internal/ld/outbuf_nommap.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build !darwin,!dragonfly,!freebsd,!linux,!openbsd,!windows
+// +build !aix,!darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!windows
 
 package ld
 
diff --git a/src/cmd/link/internal/ld/outbuf_test.go b/src/cmd/link/internal/ld/outbuf_test.go
index d8c2142..db0a924 100644
--- a/src/cmd/link/internal/ld/outbuf_test.go
+++ b/src/cmd/link/internal/ld/outbuf_test.go
@@ -17,7 +17,7 @@
 	switch runtime.GOOS {
 	default:
 		t.Skip("unsupported OS")
-	case "darwin", "dragonfly", "freebsd", "linux", "openbsd", "windows":
+	case "aix", "darwin", "dragonfly", "freebsd", "linux", "netbsd", "openbsd", "windows":
 	}
 	dir, err := ioutil.TempDir("", "TestMMap")
 	if err != nil {
diff --git a/src/cmd/link/internal/ld/pcln.go b/src/cmd/link/internal/ld/pcln.go
index 5cbb7bb..a5f776e 100644
--- a/src/cmd/link/internal/ld/pcln.go
+++ b/src/cmd/link/internal/ld/pcln.go
@@ -259,7 +259,7 @@
 	//	offset to file table [4 bytes]
 
 	// Find container symbols and mark them as such.
-	for _, s := range ctxt.Textp2 {
+	for _, s := range ctxt.Textp {
 		outer := ldr.OuterSym(s)
 		if outer != 0 {
 			state.container.Set(outer)
@@ -268,8 +268,8 @@
 
 	// Gather some basic stats and info.
 	var nfunc int32
-	prevSect := ldr.SymSect(ctxt.Textp2[0])
-	for _, s := range ctxt.Textp2 {
+	prevSect := ldr.SymSect(ctxt.Textp[0])
+	for _, s := range ctxt.Textp {
 		if !emitPcln(ctxt, s, state.container) {
 			continue
 		}
@@ -297,7 +297,7 @@
 	ftab.SetUint(ctxt.Arch, 8, uint64(nfunc))
 	pclntabPclntabOffset = int32(8 + ctxt.Arch.PtrSize)
 
-	szHint := len(ctxt.Textp2) * 2
+	szHint := len(ctxt.Textp) * 2
 	funcnameoff := make(map[string]int32, szHint)
 	nameToOffset := func(name string) int32 {
 		nameoff, ok := funcnameoff[name]
@@ -350,8 +350,8 @@
 	funcdataoff := []int64{}
 
 	nfunc = 0 // repurpose nfunc as a running index
-	prevFunc := ctxt.Textp2[0]
-	for _, s := range ctxt.Textp2 {
+	prevFunc := ctxt.Textp[0]
+	for _, s := range ctxt.Textp {
 		if !emitPcln(ctxt, s, state.container) {
 			continue
 		}
@@ -524,7 +524,7 @@
 		nfunc++
 	}
 
-	last := ctxt.Textp2[len(ctxt.Textp2)-1]
+	last := ctxt.Textp[len(ctxt.Textp)-1]
 	pclntabLastFunc = last
 	// Final entry of table is just end pc.
 	setAddr(ftab, ctxt.Arch, 8+int64(ctxt.Arch.PtrSize)+int64(nfunc)*2*int64(ctxt.Arch.PtrSize), last, ldr.SymSize(last))
@@ -592,8 +592,8 @@
 	ldr.SetAttrLocal(tsym, true)
 
 	// find min and max address
-	min := ldr.SymValue(ctxt.Textp2[0])
-	lastp := ctxt.Textp2[len(ctxt.Textp2)-1]
+	min := ldr.SymValue(ctxt.Textp[0])
+	lastp := ctxt.Textp[len(ctxt.Textp)-1]
 	max := ldr.SymValue(lastp) + ldr.SymSize(lastp)
 
 	// for each subbucket, compute the minimum of all symbol indexes
@@ -605,18 +605,18 @@
 		indexes[i] = NOIDX
 	}
 	idx := int32(0)
-	for i, s := range ctxt.Textp2 {
+	for i, s := range ctxt.Textp {
 		if !emitPcln(ctxt, s, container) {
 			continue
 		}
 		p := ldr.SymValue(s)
 		var e loader.Sym
 		i++
-		if i < len(ctxt.Textp2) {
-			e = ctxt.Textp2[i]
+		if i < len(ctxt.Textp) {
+			e = ctxt.Textp[i]
 		}
-		for e != 0 && !emitPcln(ctxt, e, container) && i < len(ctxt.Textp2) {
-			e = ctxt.Textp2[i]
+		for e != 0 && !emitPcln(ctxt, e, container) && i < len(ctxt.Textp) {
+			e = ctxt.Textp[i]
 			i++
 		}
 		q := max
diff --git a/src/cmd/link/internal/ld/pe.go b/src/cmd/link/internal/ld/pe.go
index 362d2fd..f0211e1 100644
--- a/src/cmd/link/internal/ld/pe.go
+++ b/src/cmd/link/internal/ld/pe.go
@@ -472,8 +472,8 @@
 	ctxt.Out.SeekSet(int64(sect.pointerToRawData))
 	sect.checkOffset(ctxt.Out.Offset())
 
-	init_entry := ctxt.Syms.Lookup(*flagEntrySymbol, 0)
-	addr := uint64(init_entry.Value) - init_entry.Sect.Vaddr
+	init_entry := ctxt.loader.Lookup(*flagEntrySymbol, 0)
+	addr := uint64(ctxt.loader.SymValue(init_entry)) - ctxt.loader.SymSect(init_entry).Vaddr
 	switch objabi.GOARCH {
 	case "386", "arm":
 		ctxt.Out.Write32(uint32(addr))
@@ -489,58 +489,58 @@
 		ctxt.Out.Write8(0)
 	}
 
+	ldr := ctxt.loader
+
 	// relocsect relocates symbols from first in section sect, and returns
 	// the total number of relocations emitted.
-	relocsect := func(sect *sym.Section, syms []*sym.Symbol, base uint64) int {
+	relocsect := func(sect *sym.Section, syms []loader.Sym, base uint64) int {
 		// If main section has no bits, nothing to relocate.
 		if sect.Vaddr >= sect.Seg.Vaddr+sect.Seg.Filelen {
 			return 0
 		}
-		relocs := 0
+		nrelocs := 0
 		sect.Reloff = uint64(ctxt.Out.Offset())
 		for i, s := range syms {
-			if !s.Attr.Reachable() {
+			if !ldr.AttrReachable(s) {
 				continue
 			}
-			if uint64(s.Value) >= sect.Vaddr {
+			if uint64(ldr.SymValue(s)) >= sect.Vaddr {
 				syms = syms[i:]
 				break
 			}
 		}
 		eaddr := int32(sect.Vaddr + sect.Length)
-		for _, sym := range syms {
-			if !sym.Attr.Reachable() {
+		for _, s := range syms {
+			if !ldr.AttrReachable(s) {
 				continue
 			}
-			if sym.Value >= int64(eaddr) {
+			if ldr.SymValue(s) >= int64(eaddr) {
 				break
 			}
-			for ri := range sym.R {
-				r := &sym.R[ri]
-				if r.Done {
+			relocs := ldr.ExtRelocs(s)
+			for ri := 0; ri < relocs.Count(); ri++ {
+				r := relocs.At(ri)
+				if r.Xsym == 0 {
+					ctxt.Errorf(s, "missing xsym in relocation")
 					continue
 				}
-				if r.Xsym == nil {
-					Errorf(sym, "missing xsym in relocation")
-					continue
+				if ldr.SymDynid(r.Xsym) < 0 {
+					ctxt.Errorf(s, "reloc %d to non-coff symbol %s (outer=%s) %d", r.Type(), ldr.SymName(r.Sym()), ldr.SymName(r.Xsym), ldr.SymType(r.Sym()))
 				}
-				if r.Xsym.Dynid < 0 {
-					Errorf(sym, "reloc %d to non-coff symbol %s (outer=%s) %d", r.Type, r.Sym.Name, r.Xsym.Name, r.Sym.Type)
+				if !thearch.PEreloc1(ctxt.Arch, ctxt.Out, ldr, s, r, int64(uint64(ldr.SymValue(s)+int64(r.Off()))-base)) {
+					ctxt.Errorf(s, "unsupported obj reloc %d/%d to %s", r.Type(), r.Siz(), ldr.SymName(r.Sym()))
 				}
-				if !thearch.PEreloc1(ctxt.Arch, ctxt.Out, sym, r, int64(uint64(sym.Value+int64(r.Off))-base)) {
-					Errorf(sym, "unsupported obj reloc %d/%d to %s", r.Type, r.Siz, r.Sym.Name)
-				}
-				relocs++
+				nrelocs++
 			}
 		}
 		sect.Rellen = uint64(ctxt.Out.Offset()) - sect.Reloff
-		return relocs
+		return nrelocs
 	}
 
 	sects := []struct {
 		peSect *peSection
 		seg    *sym.Segment
-		syms   []*sym.Symbol
+		syms   []loader.Sym
 	}{
 		{f.textSect, &Segtext, ctxt.Textp},
 		{f.rdataSect, &Segrodata, ctxt.datap},
@@ -560,8 +560,8 @@
 	for i := 0; i < len(Segdwarf.Sections); i++ {
 		sect := Segdwarf.Sections[i]
 		si := dwarfp[i]
-		if si.secSym() != sect.Sym ||
-			si.secSym().Sect != sect {
+		if si.secSym() != loader.Sym(sect.Sym) ||
+			ldr.SymSect(si.secSym()) != sect {
 			panic("inconsistency between dwarfp and Segdwarf")
 		}
 		for _, pesect := range f.sections {
@@ -576,12 +576,12 @@
 	}
 
 	f.ctorsSect.emitRelocations(ctxt.Out, func() int {
-		dottext := ctxt.Syms.Lookup(".text", 0)
+		dottext := ldr.Lookup(".text", 0)
 		ctxt.Out.Write32(0)
-		ctxt.Out.Write32(uint32(dottext.Dynid))
+		ctxt.Out.Write32(uint32(ldr.SymDynid(dottext)))
 		switch objabi.GOARCH {
 		default:
-			Errorf(dottext, "unknown architecture for PE: %q\n", objabi.GOARCH)
+			ctxt.Errorf(dottext, "unknown architecture for PE: %q\n", objabi.GOARCH)
 		case "386":
 			ctxt.Out.Write16(IMAGE_REL_I386_DIR32)
 		case "amd64":
@@ -595,12 +595,12 @@
 
 // writeSymbol appends symbol s to file f symbol table.
 // It also sets s.Dynid to written symbol number.
-func (f *peFile) writeSymbol(out *OutBuf, s *sym.Symbol, value int64, sectidx int, typ uint16, class uint8) {
-	if len(s.Name) > 8 {
+func (f *peFile) writeSymbol(out *OutBuf, ldr *loader.Loader, s loader.Sym, name string, value int64, sectidx int, typ uint16, class uint8) {
+	if len(name) > 8 {
 		out.Write32(0)
-		out.Write32(uint32(f.stringTable.add(s.Name)))
+		out.Write32(uint32(f.stringTable.add(name)))
 	} else {
-		out.WriteStringN(s.Name, 8)
+		out.WriteStringN(name, 8)
 	}
 	out.Write32(uint32(value))
 	out.Write16(uint16(sectidx))
@@ -608,31 +608,32 @@
 	out.Write8(class)
 	out.Write8(0) // no aux entries
 
-	s.Dynid = int32(f.symbolCount)
+	ldr.SetSymDynid(s, int32(f.symbolCount))
 
 	f.symbolCount++
 }
 
 // mapToPESection searches peFile f for s symbol's location.
 // It returns PE section index, and offset within that section.
-func (f *peFile) mapToPESection(s *sym.Symbol, linkmode LinkMode) (pesectidx int, offset int64, err error) {
-	if s.Sect == nil {
-		return 0, 0, fmt.Errorf("could not map %s symbol with no section", s.Name)
+func (f *peFile) mapToPESection(ldr *loader.Loader, s loader.Sym, linkmode LinkMode) (pesectidx int, offset int64, err error) {
+	sect := ldr.SymSect(s)
+	if sect == nil {
+		return 0, 0, fmt.Errorf("could not map %s symbol with no section", ldr.SymName(s))
 	}
-	if s.Sect.Seg == &Segtext {
-		return f.textSect.index, int64(uint64(s.Value) - Segtext.Vaddr), nil
+	if sect.Seg == &Segtext {
+		return f.textSect.index, int64(uint64(ldr.SymValue(s)) - Segtext.Vaddr), nil
 	}
-	if s.Sect.Seg == &Segrodata {
-		return f.rdataSect.index, int64(uint64(s.Value) - Segrodata.Vaddr), nil
+	if sect.Seg == &Segrodata {
+		return f.rdataSect.index, int64(uint64(ldr.SymValue(s)) - Segrodata.Vaddr), nil
 	}
-	if s.Sect.Seg != &Segdata {
-		return 0, 0, fmt.Errorf("could not map %s symbol with non .text or .rdata or .data section", s.Name)
+	if sect.Seg != &Segdata {
+		return 0, 0, fmt.Errorf("could not map %s symbol with non .text or .rdata or .data section", ldr.SymName(s))
 	}
-	v := uint64(s.Value) - Segdata.Vaddr
+	v := uint64(ldr.SymValue(s)) - Segdata.Vaddr
 	if linkmode != LinkExternal {
 		return f.dataSect.index, int64(v), nil
 	}
-	if s.Type == sym.SDATA {
+	if ldr.SymType(s) == sym.SDATA {
 		return f.dataSect.index, int64(v), nil
 	}
 	// Note: although address of runtime.edata (type sym.SDATA) is at the start of .bss section
@@ -645,60 +646,100 @@
 
 // writeSymbols writes all COFF symbol table records.
 func (f *peFile) writeSymbols(ctxt *Link) {
+	ldr := ctxt.loader
+	addsym := func(s loader.Sym) {
+		t := ldr.SymType(s)
+		if ldr.SymSect(s) == nil && t != sym.SDYNIMPORT && t != sym.SHOSTOBJ && t != sym.SUNDEFEXT {
+			return
+		}
 
-	put := func(ctxt *Link, s *sym.Symbol, name string, type_ SymbolType, addr int64) {
-		if s == nil {
-			return
-		}
-		if s.Sect == nil && type_ != UndefinedSym {
-			return
-		}
-		switch type_ {
-		default:
-			return
-		case DataSym, BSSSym, TextSym, UndefinedSym:
-		}
+		name := ldr.SymName(s)
 
 		// Only windows/386 requires underscore prefix on external symbols.
-		if ctxt.Arch.Family == sys.I386 &&
-			ctxt.LinkMode == LinkExternal &&
-			(s.Type == sym.SHOSTOBJ || s.Type == sym.SUNDEFEXT || s.Attr.CgoExport()) {
-			s.Name = "_" + s.Name
+		if ctxt.Is386() && ctxt.IsExternal() &&
+			(t == sym.SHOSTOBJ || t == sym.SUNDEFEXT || ldr.AttrCgoExport(s)) {
+			name = "_" + name
 		}
 
-		var typ uint16
-		if ctxt.LinkMode == LinkExternal {
-			typ = IMAGE_SYM_TYPE_NULL
+		var peSymType uint16
+		if ctxt.IsExternal() {
+			peSymType = IMAGE_SYM_TYPE_NULL
 		} else {
 			// TODO: fix IMAGE_SYM_DTYPE_ARRAY value and use following expression, instead of 0x0308
-			typ = IMAGE_SYM_DTYPE_ARRAY<<8 + IMAGE_SYM_TYPE_STRUCT
-			typ = 0x0308 // "array of structs"
+			// peSymType = IMAGE_SYM_DTYPE_ARRAY<<8 + IMAGE_SYM_TYPE_STRUCT
+			peSymType = 0x0308 // "array of structs"
 		}
-		sect, value, err := f.mapToPESection(s, ctxt.LinkMode)
+		sect, value, err := f.mapToPESection(ldr, s, ctxt.LinkMode)
 		if err != nil {
-			if type_ == UndefinedSym {
-				typ = IMAGE_SYM_DTYPE_FUNCTION
+			if t == sym.SDYNIMPORT || t == sym.SHOSTOBJ || t == sym.SUNDEFEXT {
+				peSymType = IMAGE_SYM_DTYPE_FUNCTION
 			} else {
-				Errorf(s, "addpesym: %v", err)
+				ctxt.Errorf(s, "addpesym: %v", err)
 			}
 		}
 		class := IMAGE_SYM_CLASS_EXTERNAL
-		if s.IsFileLocal() || s.Attr.VisibilityHidden() || s.Attr.Local() {
+		if ldr.IsFileLocal(s) || ldr.AttrVisibilityHidden(s) || ldr.AttrLocal(s) {
 			class = IMAGE_SYM_CLASS_STATIC
 		}
-		f.writeSymbol(ctxt.Out, s, value, sect, typ, uint8(class))
+		f.writeSymbol(ctxt.Out, ldr, s, name, value, sect, peSymType, uint8(class))
 	}
 
 	if ctxt.LinkMode == LinkExternal {
 		// Include section symbols as external, because
 		// .ctors and .debug_* section relocations refer to it.
 		for _, pesect := range f.sections {
-			sym := ctxt.Syms.Lookup(pesect.name, 0)
-			f.writeSymbol(ctxt.Out, sym, 0, pesect.index, IMAGE_SYM_TYPE_NULL, IMAGE_SYM_CLASS_STATIC)
+			s := ldr.LookupOrCreateSym(pesect.name, 0)
+			f.writeSymbol(ctxt.Out, ldr, s, pesect.name, 0, pesect.index, IMAGE_SYM_TYPE_NULL, IMAGE_SYM_CLASS_STATIC)
 		}
 	}
 
-	genasmsym(ctxt, put)
+	// Add special runtime.text and runtime.etext symbols.
+	s := ldr.Lookup("runtime.text", 0)
+	if ldr.SymType(s) == sym.STEXT {
+		addsym(s)
+	}
+	s = ldr.Lookup("runtime.etext", 0)
+	if ldr.SymType(s) == sym.STEXT {
+		addsym(s)
+	}
+
+	// Add text symbols.
+	for _, s := range ctxt.Textp {
+		addsym(s)
+	}
+
+	shouldBeInSymbolTable := func(s loader.Sym) bool {
+		if ldr.AttrNotInSymbolTable(s) {
+			return false
+		}
+		name := ldr.RawSymName(s) // TODO: try not to read the name
+		if name == "" || name[0] == '.' {
+			return false
+		}
+		return true
+	}
+
+	// Add data symbols and external references.
+	for s := loader.Sym(1); s < loader.Sym(ldr.NSym()); s++ {
+		if !ldr.AttrReachable(s) {
+			continue
+		}
+		t := ldr.SymType(s)
+		if t >= sym.SELFRXSECT && t < sym.SXREF { // data sections handled in dodata
+			if t == sym.STLSBSS {
+				continue
+			}
+			if !shouldBeInSymbolTable(s) {
+				continue
+			}
+			addsym(s)
+		}
+
+		switch t {
+		case sym.SDYNIMPORT, sym.SHOSTOBJ, sym.SUNDEFEXT:
+			addsym(s)
+		}
+	}
 }
 
 // writeSymbolTableAndStringTable writes out symbol and string tables for peFile f.
@@ -1109,7 +1150,7 @@
 func addimports(ctxt *Link, datsect *peSection) {
 	ldr := ctxt.loader
 	startoff := ctxt.Out.Offset()
-	dynamic := ctxt.Syms.Lookup(".windynamic", 0)
+	dynamic := ldr.LookupOrCreateSym(".windynamic", 0)
 
 	// skip import descriptor table (will write it later)
 	n := uint64(0)
@@ -1130,7 +1171,7 @@
 		for m := d.ms; m != nil; m = m.next {
 			m.off = uint64(pefile.nextSectOffset) + uint64(ctxt.Out.Offset()) - uint64(startoff)
 			ctxt.Out.Write16(0) // hint
-			strput(ctxt.Out, ldr.Syms[m.s].Extname())
+			strput(ctxt.Out, ldr.SymExtname(m.s))
 		}
 	}
 
@@ -1165,7 +1206,7 @@
 	endoff := ctxt.Out.Offset()
 
 	// write FirstThunks (allocated in .data section)
-	ftbase := uint64(dynamic.Value) - uint64(datsect.virtualAddress) - PEBASE
+	ftbase := uint64(ldr.SymValue(dynamic)) - uint64(datsect.virtualAddress) - PEBASE
 
 	ctxt.Out.SeekSet(int64(uint64(datsect.pointerToRawData) + ftbase))
 	for d := dr; d != nil; d = d.next {
@@ -1205,8 +1246,8 @@
 	// update data directory
 	pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress = isect.virtualAddress
 	pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_IMPORT].Size = isect.virtualSize
-	pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress = uint32(dynamic.Value - PEBASE)
-	pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_IAT].Size = uint32(dynamic.Size)
+	pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress = uint32(ldr.SymValue(dynamic) - PEBASE)
+	pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_IAT].Size = uint32(ldr.SymSize(dynamic))
 
 	out.SeekSet(endoff)
 }
@@ -1235,7 +1276,7 @@
 	nexport := len(dexport)
 	size := binary.Size(&e) + 10*nexport + len(*flagOutfile) + 1
 	for _, s := range dexport {
-		size += len(ldr.Syms[s].Extname()) + 1
+		size += len(ldr.SymExtname(s)) + 1
 	}
 
 	if nexport == 0 {
@@ -1271,7 +1312,7 @@
 
 	// put EXPORT Address Table
 	for _, s := range dexport {
-		out.Write32(uint32(ldr.Syms[s].Value - PEBASE))
+		out.Write32(uint32(ldr.SymValue(s) - PEBASE))
 	}
 
 	// put EXPORT Name Pointer Table
@@ -1279,7 +1320,7 @@
 
 	for _, s := range dexport {
 		out.Write32(uint32(v))
-		v += len(ldr.Syms[s].Extname()) + 1
+		v += len(ldr.SymExtname(s)) + 1
 	}
 
 	// put EXPORT Ordinal Table
@@ -1291,8 +1332,8 @@
 	out.WriteStringN(*flagOutfile, len(*flagOutfile)+1)
 
 	for _, s := range dexport {
-		ss := ldr.Syms[s]
-		out.WriteStringN(ss.Extname(), len(ss.Extname())+1)
+		name := ldr.SymExtname(s)
+		out.WriteStringN(name, len(name)+1)
 	}
 	sect.pad(out, uint32(size))
 }
@@ -1300,8 +1341,6 @@
 // peBaseRelocEntry represents a single relocation entry.
 type peBaseRelocEntry struct {
 	typeOff uint16
-	rel     *sym.Reloc
-	sym     *sym.Symbol // For debug
 }
 
 // peBaseRelocBlock represents a Base Relocation Block. A block
@@ -1338,13 +1377,13 @@
 	rt.blocks = make(map[uint32]peBaseRelocBlock)
 }
 
-func (rt *peBaseRelocTable) addentry(ctxt *Link, s *sym.Symbol, r *sym.Reloc) {
+func (rt *peBaseRelocTable) addentry(ldr *loader.Loader, s loader.Sym, r *loader.Reloc2) {
 	// pageSize is the size in bytes of a page
 	// described by a base relocation block.
 	const pageSize = 0x1000
 	const pageMask = pageSize - 1
 
-	addr := s.Value + int64(r.Off) - int64(PEBASE)
+	addr := ldr.SymValue(s) + int64(r.Off()) - int64(PEBASE)
 	page := uint32(addr &^ pageMask)
 	off := uint32(addr & pageMask)
 
@@ -1355,12 +1394,10 @@
 
 	e := peBaseRelocEntry{
 		typeOff: uint16(off & 0xFFF),
-		rel:     r,
-		sym:     s,
 	}
 
 	// Set entry type
-	switch r.Siz {
+	switch r.Siz() {
 	default:
 		Exitf("unsupported relocation size %d\n", r.Siz)
 	case 4:
@@ -1392,30 +1429,32 @@
 	}
 }
 
-func addPEBaseRelocSym(ctxt *Link, s *sym.Symbol, rt *peBaseRelocTable) {
-	for ri := 0; ri < len(s.R); ri++ {
-		r := &s.R[ri]
-
-		if r.Sym == nil {
+func addPEBaseRelocSym(ldr *loader.Loader, s loader.Sym, rt *peBaseRelocTable) {
+	relocs := ldr.Relocs(s)
+	for ri := 0; ri < relocs.Count(); ri++ {
+		r := relocs.At2(ri)
+		if r.Type() >= objabi.ElfRelocOffset {
 			continue
 		}
-		if !r.Sym.Attr.Reachable() {
+		if r.Siz() == 0 { // informational relocation
 			continue
 		}
-		if r.Type >= objabi.ElfRelocOffset {
+		if r.Type() == objabi.R_DWARFFILEREF {
 			continue
 		}
-		if r.Siz == 0 { // informational relocation
+		rs := r.Sym()
+		rs = ldr.ResolveABIAlias(rs)
+		if rs == 0 {
 			continue
 		}
-		if r.Type == objabi.R_DWARFFILEREF {
+		if !ldr.AttrReachable(s) {
 			continue
 		}
 
-		switch r.Type {
+		switch r.Type() {
 		default:
 		case objabi.R_ADDR:
-			rt.addentry(ctxt, s, r)
+			rt.addentry(ldr, s, &r)
 		}
 	}
 }
@@ -1437,11 +1476,12 @@
 	rt.init(ctxt)
 
 	// Get relocation information
+	ldr := ctxt.loader
 	for _, s := range ctxt.Textp {
-		addPEBaseRelocSym(ctxt, s, &rt)
+		addPEBaseRelocSym(ldr, s, &rt)
 	}
 	for _, s := range ctxt.datap {
-		addPEBaseRelocSym(ctxt, s, &rt)
+		addPEBaseRelocSym(ldr, s, &rt)
 	}
 
 	// Write relocation information
@@ -1507,7 +1547,7 @@
 	pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_RESOURCE].Size = h.virtualSize
 }
 
-func Asmbpe(ctxt *Link) {
+func asmbPe(ctxt *Link) {
 	switch ctxt.Arch.Family {
 	default:
 		Exitf("unknown PE architecture: %v", ctxt.Arch.Family)
diff --git a/src/cmd/link/internal/ld/sym.go b/src/cmd/link/internal/ld/sym.go
index 1b7d9d5..3f26945 100644
--- a/src/cmd/link/internal/ld/sym.go
+++ b/src/cmd/link/internal/ld/sym.go
@@ -44,7 +44,7 @@
 	ler := loader.ErrorReporter{AfterErrorAction: afterErrorAction}
 	ctxt := &Link{
 		Target:        Target{Arch: arch},
-		Syms:          sym.NewSymbols(),
+		version:       sym.SymVerStatic,
 		outSem:        make(chan int, 2*runtime.GOMAXPROCS(0)),
 		Out:           NewOutBuf(arch),
 		LibraryByPkg:  make(map[string]*sym.Library),
diff --git a/src/cmd/link/internal/ld/symtab.go b/src/cmd/link/internal/ld/symtab.go
index 46aa33b..577c24e 100644
--- a/src/cmd/link/internal/ld/symtab.go
+++ b/src/cmd/link/internal/ld/symtab.go
@@ -32,7 +32,6 @@
 
 import (
 	"cmd/internal/objabi"
-	"cmd/internal/sys"
 	"cmd/link/internal/loader"
 	"cmd/link/internal/sym"
 	"fmt"
@@ -62,7 +61,7 @@
 		out.Write16(uint16(shndx))
 		out.Write64(uint64(addr))
 		out.Write64(uint64(size))
-		Symsize += ELF64SYMSIZE
+		symSize += ELF64SYMSIZE
 	} else {
 		out.Write32(uint32(off))
 		out.Write32(uint32(addr))
@@ -70,62 +69,42 @@
 		out.Write8(uint8(info))
 		out.Write8(uint8(other))
 		out.Write16(uint16(shndx))
-		Symsize += ELF32SYMSIZE
+		symSize += ELF32SYMSIZE
 	}
 }
 
-func putelfsym(ctxt *Link, x *sym.Symbol, s string, t SymbolType, addr int64) {
-	var typ int
-
-	switch t {
-	default:
-		return
-
-	case TextSym:
-		typ = STT_FUNC
-
-	case DataSym, BSSSym:
-		typ = STT_OBJECT
-
-	case UndefinedSym:
-		// ElfType is only set for symbols read from Go shared libraries, but
-		// for other symbols it is left as STT_NOTYPE which is fine.
-		typ = int(x.ElfType())
-
-	case TLSSym:
-		typ = STT_TLS
-	}
-
-	size := x.Size
-	if t == UndefinedSym {
-		size = 0
-	}
+func putelfsym(ctxt *Link, x loader.Sym, typ int, curbind int) {
+	ldr := ctxt.loader
+	addr := ldr.SymValue(x)
+	size := ldr.SymSize(x)
 
 	xo := x
-	for xo.Outer != nil {
-		xo = xo.Outer
+	if ldr.OuterSym(x) != 0 {
+		xo = ldr.OuterSym(x)
 	}
+	xot := ldr.SymType(xo)
+	xosect := ldr.SymSect(xo)
 
 	var elfshnum int
-	if xo.Type == sym.SDYNIMPORT || xo.Type == sym.SHOSTOBJ || xo.Type == sym.SUNDEFEXT {
+	if xot == sym.SDYNIMPORT || xot == sym.SHOSTOBJ || xot == sym.SUNDEFEXT {
 		elfshnum = SHN_UNDEF
+		size = 0
 	} else {
-		if xo.Sect == nil {
-			Errorf(x, "missing section in putelfsym")
+		if xosect == nil {
+			ldr.Errorf(x, "missing section in putelfsym")
 			return
 		}
-		if xo.Sect.Elfsect == nil {
-			Errorf(x, "missing ELF section in putelfsym")
+		if xosect.Elfsect == nil {
+			ldr.Errorf(x, "missing ELF section in putelfsym")
 			return
 		}
-		elfshnum = xo.Sect.Elfsect.(*ElfShdr).shnum
+		elfshnum = xosect.Elfsect.(*ElfShdr).shnum
 	}
 
 	// One pass for each binding: STB_LOCAL, STB_GLOBAL,
 	// maybe one day STB_WEAK.
 	bind := STB_GLOBAL
-
-	if x.IsFileLocal() || x.Attr.VisibilityHidden() || x.Attr.Local() {
+	if ldr.IsFileLocal(x) || ldr.AttrVisibilityHidden(x) || ldr.AttrLocal(x) {
 		bind = STB_LOCAL
 	}
 
@@ -134,15 +113,15 @@
 	// To avoid filling the dynamic table with lots of unnecessary symbols,
 	// mark all Go symbols local (not global) in the final executable.
 	// But when we're dynamically linking, we need all those global symbols.
-	if !ctxt.DynlinkingGo() && ctxt.LinkMode == LinkExternal && !x.Attr.CgoExportStatic() && elfshnum != SHN_UNDEF {
+	if !ctxt.DynlinkingGo() && ctxt.IsExternal() && !ldr.AttrCgoExportStatic(x) && elfshnum != SHN_UNDEF {
 		bind = STB_LOCAL
 	}
 
 	if ctxt.LinkMode == LinkExternal && elfshnum != SHN_UNDEF {
-		addr -= int64(xo.Sect.Vaddr)
+		addr -= int64(xosect.Vaddr)
 	}
 	other := STV_DEFAULT
-	if x.Attr.VisibilityHidden() {
+	if ldr.AttrVisibilityHidden(x) {
 		// TODO(mwhudson): We only set AttrVisibilityHidden in ldelf, i.e. when
 		// internally linking. But STV_HIDDEN visibility only matters in object
 		// files and shared libraries, and as we are a long way from implementing
@@ -150,7 +129,7 @@
 		// externally linking, I don't think this makes a lot of sense.
 		other = STV_HIDDEN
 	}
-	if ctxt.Arch.Family == sys.PPC64 && typ == STT_FUNC && x.Attr.Shared() && x.Name != "runtime.duffzero" && x.Name != "runtime.duffcopy" {
+	if ctxt.IsPPC64() && typ == STT_FUNC && ldr.AttrShared(x) && ldr.SymName(x) != "runtime.duffzero" && ldr.SymName(x) != "runtime.duffcopy" {
 		// On ppc64 the top three bits of the st_other field indicate how
 		// many instructions separate the global and local entry points. In
 		// our case it is two instructions, indicated by the value 3.
@@ -160,22 +139,17 @@
 		other |= 3 << 5
 	}
 
-	if s == x.Name {
-		// We should use Extname for ELF symbol table.
-		// TODO: maybe genasmsym should have done this. That function is too
-		// overloaded and I would rather not change it for now.
-		s = x.Extname()
-	}
+	sname := ldr.SymExtname(x)
 
 	// When dynamically linking, we create Symbols by reading the names from
 	// the symbol tables of the shared libraries and so the names need to
 	// match exactly. Tools like DTrace will have to wait for now.
 	if !ctxt.DynlinkingGo() {
 		// Rewrite · to . for ASCII-only tools like DTrace (sigh)
-		s = strings.Replace(s, "·", ".", -1)
+		sname = strings.Replace(sname, "·", ".", -1)
 	}
 
-	if ctxt.DynlinkingGo() && bind == STB_GLOBAL && ctxt.elfbind == STB_LOCAL && x.Type == sym.STEXT {
+	if ctxt.DynlinkingGo() && bind == STB_GLOBAL && curbind == STB_LOCAL && ldr.SymType(x) == sym.STEXT {
 		// When dynamically linking, we want references to functions defined
 		// in this module to always be to the function object, not to the
 		// PLT. We force this by writing an additional local symbol for every
@@ -184,26 +158,79 @@
 		// (*sym.Symbol).ElfsymForReloc). This is approximately equivalent to the
 		// ELF linker -Bsymbolic-functions option, but that is buggy on
 		// several platforms.
-		putelfsyment(ctxt.Out, putelfstr("local."+s), addr, size, STB_LOCAL<<4|typ&0xf, elfshnum, other)
-		ctxt.loader.SetSymLocalElfSym(loader.Sym(x.SymIdx), int32(ctxt.numelfsym))
+		putelfsyment(ctxt.Out, putelfstr("local."+sname), addr, size, STB_LOCAL<<4|typ&0xf, elfshnum, other)
+		ldr.SetSymLocalElfSym(x, int32(ctxt.numelfsym))
 		ctxt.numelfsym++
 		return
-	} else if bind != ctxt.elfbind {
+	} else if bind != curbind {
 		return
 	}
 
-	putelfsyment(ctxt.Out, putelfstr(s), addr, size, bind<<4|typ&0xf, elfshnum, other)
-	ctxt.loader.SetSymElfSym(loader.Sym(x.SymIdx), int32(ctxt.numelfsym))
+	putelfsyment(ctxt.Out, putelfstr(sname), addr, size, bind<<4|typ&0xf, elfshnum, other)
+	ldr.SetSymElfSym(x, int32(ctxt.numelfsym))
 	ctxt.numelfsym++
 }
 
-func putelfsectionsym(ctxt *Link, out *OutBuf, s *sym.Symbol, shndx int) {
+func putelfsectionsym(ctxt *Link, out *OutBuf, s loader.Sym, shndx int) {
 	putelfsyment(out, 0, 0, 0, STB_LOCAL<<4|STT_SECTION, shndx, 0)
-	ctxt.loader.SetSymElfSym(loader.Sym(s.SymIdx), int32(ctxt.numelfsym))
+	ctxt.loader.SetSymElfSym(s, int32(ctxt.numelfsym))
 	ctxt.numelfsym++
 }
 
-func Asmelfsym(ctxt *Link) {
+func genelfsym(ctxt *Link, elfbind int) {
+	ldr := ctxt.loader
+
+	// Text symbols.
+	s := ldr.Lookup("runtime.text", 0)
+	putelfsym(ctxt, s, STT_FUNC, elfbind)
+	for _, s := range ctxt.Textp {
+		putelfsym(ctxt, s, STT_FUNC, elfbind)
+	}
+	s = ldr.Lookup("runtime.etext", 0)
+	if ldr.SymType(s) == sym.STEXT {
+		putelfsym(ctxt, s, STT_FUNC, elfbind)
+	}
+
+	shouldBeInSymbolTable := func(s loader.Sym) bool {
+		if ldr.AttrNotInSymbolTable(s) {
+			return false
+		}
+		// FIXME: avoid having to do name inspections here.
+		sn := ldr.SymName(s)
+		if (sn == "" || sn[0] == '.') && !ldr.IsFileLocal(s) {
+			return false
+		}
+		return true
+	}
+
+	// Data symbols.
+	for s := loader.Sym(1); s < loader.Sym(ldr.NSym()); s++ {
+		if !ldr.AttrReachable(s) {
+			continue
+		}
+		st := ldr.SymType(s)
+		if st >= sym.SELFRXSECT && st < sym.SXREF {
+			typ := STT_OBJECT
+			if st == sym.STLSBSS {
+				if ctxt.IsInternal() {
+					continue
+				}
+				typ = STT_TLS
+			}
+			if !shouldBeInSymbolTable(s) {
+				continue
+			}
+			putelfsym(ctxt, s, typ, elfbind)
+			continue
+		}
+		if st == sym.SHOSTOBJ || st == sym.SDYNIMPORT || st == sym.SUNDEFEXT {
+			putelfsym(ctxt, s, int(ldr.SymElfType(s)), elfbind)
+		}
+	}
+}
+
+func asmElfSym(ctxt *Link) {
+
 	// the first symbol entry is reserved
 	putelfsyment(ctxt.Out, 0, 0, 0, STB_LOCAL<<4|STT_NOTYPE, 0, 0)
 
@@ -216,45 +243,86 @@
 	putelfsyment(ctxt.Out, putelfstr("go.go"), 0, 0, STB_LOCAL<<4|STT_FILE, SHN_ABS, 0)
 	ctxt.numelfsym++
 
-	ctxt.elfbind = STB_LOCAL
-	genasmsym(ctxt, putelfsym)
-
-	ctxt.elfbind = STB_GLOBAL
-	elfglobalsymndx = ctxt.numelfsym
-	genasmsym(ctxt, putelfsym)
-}
-
-func putplan9sym(ctxt *Link, x *sym.Symbol, s string, typ SymbolType, addr int64) {
-	t := int(typ)
-	switch typ {
-	case TextSym, DataSym, BSSSym:
-		if x.IsFileLocal() {
-			t += 'a' - 'A'
+	bindings := []int{STB_LOCAL, STB_GLOBAL}
+	for _, elfbind := range bindings {
+		if elfbind == STB_GLOBAL {
+			elfglobalsymndx = ctxt.numelfsym
 		}
-		fallthrough
-
-	case AutoSym, ParamSym, FrameSym:
-		l := 4
-		if ctxt.HeadType == objabi.Hplan9 && ctxt.Arch.Family == sys.AMD64 && !Flag8 {
-			ctxt.Out.Write32b(uint32(addr >> 32))
-			l = 8
-		}
-
-		ctxt.Out.Write32b(uint32(addr))
-		ctxt.Out.Write8(uint8(t + 0x80)) /* 0x80 is variable length */
-
-		ctxt.Out.WriteString(s)
-		ctxt.Out.Write8(0)
-
-		Symsize += int32(l) + 1 + int32(len(s)) + 1
-
-	default:
-		return
+		genelfsym(ctxt, elfbind)
 	}
 }
 
-func Asmplan9sym(ctxt *Link) {
-	genasmsym(ctxt, putplan9sym)
+func putplan9sym(ctxt *Link, ldr *loader.Loader, s loader.Sym, char SymbolType) {
+	t := int(char)
+	if ldr.IsFileLocal(s) {
+		t += 'a' - 'A'
+	}
+	l := 4
+	addr := ldr.SymValue(s)
+	if ctxt.IsAMD64() && !flag8 {
+		ctxt.Out.Write32b(uint32(addr >> 32))
+		l = 8
+	}
+
+	ctxt.Out.Write32b(uint32(addr))
+	ctxt.Out.Write8(uint8(t + 0x80)) /* 0x80 is variable length */
+
+	name := ldr.SymName(s)
+	ctxt.Out.WriteString(name)
+	ctxt.Out.Write8(0)
+
+	symSize += int32(l) + 1 + int32(len(name)) + 1
+}
+
+func asmbPlan9Sym(ctxt *Link) {
+	ldr := ctxt.loader
+
+	// Add special runtime.text and runtime.etext symbols.
+	s := ldr.Lookup("runtime.text", 0)
+	if ldr.SymType(s) == sym.STEXT {
+		putplan9sym(ctxt, ldr, s, TextSym)
+	}
+	s = ldr.Lookup("runtime.etext", 0)
+	if ldr.SymType(s) == sym.STEXT {
+		putplan9sym(ctxt, ldr, s, TextSym)
+	}
+
+	// Add text symbols.
+	for _, s := range ctxt.Textp {
+		putplan9sym(ctxt, ldr, s, TextSym)
+	}
+
+	shouldBeInSymbolTable := func(s loader.Sym) bool {
+		if ldr.AttrNotInSymbolTable(s) {
+			return false
+		}
+		name := ldr.RawSymName(s) // TODO: try not to read the name
+		if name == "" || name[0] == '.' {
+			return false
+		}
+		return true
+	}
+
+	// Add data symbols and external references.
+	for s := loader.Sym(1); s < loader.Sym(ldr.NSym()); s++ {
+		if !ldr.AttrReachable(s) {
+			continue
+		}
+		t := ldr.SymType(s)
+		if t >= sym.SELFRXSECT && t < sym.SXREF { // data sections handled in dodata
+			if t == sym.STLSBSS {
+				continue
+			}
+			if !shouldBeInSymbolTable(s) {
+				continue
+			}
+			char := DataSym
+			if t == sym.SBSS || t == sym.SNOPTRBSS {
+				char = BSSSym
+			}
+			putplan9sym(ctxt, ldr, s, char)
+		}
+	}
 }
 
 type byPkg []*sym.Library
@@ -342,38 +410,38 @@
 
 	// Define these so that they'll get put into the symbol table.
 	// data.c:/^address will provide the actual values.
-	ctxt.xdefine2("runtime.text", sym.STEXT, 0)
-	ctxt.xdefine2("runtime.etext", sym.STEXT, 0)
-	ctxt.xdefine2("runtime.itablink", sym.SRODATA, 0)
-	ctxt.xdefine2("runtime.eitablink", sym.SRODATA, 0)
-	ctxt.xdefine2("runtime.rodata", sym.SRODATA, 0)
-	ctxt.xdefine2("runtime.erodata", sym.SRODATA, 0)
-	ctxt.xdefine2("runtime.types", sym.SRODATA, 0)
-	ctxt.xdefine2("runtime.etypes", sym.SRODATA, 0)
-	ctxt.xdefine2("runtime.noptrdata", sym.SNOPTRDATA, 0)
-	ctxt.xdefine2("runtime.enoptrdata", sym.SNOPTRDATA, 0)
-	ctxt.xdefine2("runtime.data", sym.SDATA, 0)
-	ctxt.xdefine2("runtime.edata", sym.SDATA, 0)
-	ctxt.xdefine2("runtime.bss", sym.SBSS, 0)
-	ctxt.xdefine2("runtime.ebss", sym.SBSS, 0)
-	ctxt.xdefine2("runtime.noptrbss", sym.SNOPTRBSS, 0)
-	ctxt.xdefine2("runtime.enoptrbss", sym.SNOPTRBSS, 0)
-	ctxt.xdefine2("runtime.end", sym.SBSS, 0)
-	ctxt.xdefine2("runtime.epclntab", sym.SRODATA, 0)
-	ctxt.xdefine2("runtime.esymtab", sym.SRODATA, 0)
+	ctxt.xdefine("runtime.text", sym.STEXT, 0)
+	ctxt.xdefine("runtime.etext", sym.STEXT, 0)
+	ctxt.xdefine("runtime.itablink", sym.SRODATA, 0)
+	ctxt.xdefine("runtime.eitablink", sym.SRODATA, 0)
+	ctxt.xdefine("runtime.rodata", sym.SRODATA, 0)
+	ctxt.xdefine("runtime.erodata", sym.SRODATA, 0)
+	ctxt.xdefine("runtime.types", sym.SRODATA, 0)
+	ctxt.xdefine("runtime.etypes", sym.SRODATA, 0)
+	ctxt.xdefine("runtime.noptrdata", sym.SNOPTRDATA, 0)
+	ctxt.xdefine("runtime.enoptrdata", sym.SNOPTRDATA, 0)
+	ctxt.xdefine("runtime.data", sym.SDATA, 0)
+	ctxt.xdefine("runtime.edata", sym.SDATA, 0)
+	ctxt.xdefine("runtime.bss", sym.SBSS, 0)
+	ctxt.xdefine("runtime.ebss", sym.SBSS, 0)
+	ctxt.xdefine("runtime.noptrbss", sym.SNOPTRBSS, 0)
+	ctxt.xdefine("runtime.enoptrbss", sym.SNOPTRBSS, 0)
+	ctxt.xdefine("runtime.end", sym.SBSS, 0)
+	ctxt.xdefine("runtime.epclntab", sym.SRODATA, 0)
+	ctxt.xdefine("runtime.esymtab", sym.SRODATA, 0)
 
 	// garbage collection symbols
 	s := ldr.CreateSymForUpdate("runtime.gcdata", 0)
 	s.SetType(sym.SRODATA)
 	s.SetSize(0)
 	s.SetReachable(true)
-	ctxt.xdefine2("runtime.egcdata", sym.SRODATA, 0)
+	ctxt.xdefine("runtime.egcdata", sym.SRODATA, 0)
 
 	s = ldr.CreateSymForUpdate("runtime.gcbss", 0)
 	s.SetType(sym.SRODATA)
 	s.SetSize(0)
 	s.SetReachable(true)
-	ctxt.xdefine2("runtime.egcbss", sym.SRODATA, 0)
+	ctxt.xdefine("runtime.egcbss", sym.SRODATA, 0)
 
 	// pseudo-symbols to mark locations of type, string, and go string data.
 	var symtype, symtyperel loader.Sym
@@ -523,13 +591,13 @@
 			s := ldr.CreateSymForUpdate("go.link.pkghashbytes."+l.Pkg, 0)
 			s.SetReachable(true)
 			s.SetType(sym.SRODATA)
-			s.SetSize(int64(len(l.Hash)))
-			s.SetData([]byte(l.Hash))
+			s.SetSize(int64(len(l.Fingerprint)))
+			s.SetData(l.Fingerprint[:])
 			str := ldr.CreateSymForUpdate("go.link.pkghash."+l.Pkg, 0)
 			str.SetReachable(true)
 			str.SetType(sym.SRODATA)
 			str.AddAddr(ctxt.Arch, s.Sym())
-			str.AddUint(ctxt.Arch, uint64(len(l.Hash)))
+			str.AddUint(ctxt.Arch, uint64(len(l.Fingerprint)))
 		}
 	}
 
@@ -539,7 +607,7 @@
 	// runtime to use. Any changes here must be matched by changes to
 	// the definition of moduledata in runtime/symtab.go.
 	// This code uses several global variables that are set by pcln.go:pclntab.
-	moduledata := ldr.MakeSymbolUpdater(ctxt.Moduledata2)
+	moduledata := ldr.MakeSymbolUpdater(ctxt.Moduledata)
 	pclntab := ldr.Lookup("runtime.pclntab", 0)
 	// The pclntab slice
 	moduledata.AddAddr(ctxt.Arch, pclntab)
@@ -630,7 +698,7 @@
 			// pkghashes[i].name
 			addgostring(ctxt, ldr, pkghashes, fmt.Sprintf("go.link.pkgname.%d", i), l.Pkg)
 			// pkghashes[i].linktimehash
-			addgostring(ctxt, ldr, pkghashes, fmt.Sprintf("go.link.pkglinkhash.%d", i), l.Hash)
+			addgostring(ctxt, ldr, pkghashes, fmt.Sprintf("go.link.pkglinkhash.%d", i), string(l.Fingerprint[:]))
 			// pkghashes[i].runtimehash
 			hash := ldr.Lookup("go.link.pkghash."+l.Pkg, 0)
 			pkghashes.AddAddr(ctxt.Arch, hash)
diff --git a/src/cmd/link/internal/ld/util.go b/src/cmd/link/internal/ld/util.go
index 2186503..9228ed1 100644
--- a/src/cmd/link/internal/ld/util.go
+++ b/src/cmd/link/internal/ld/util.go
@@ -6,7 +6,6 @@
 
 import (
 	"cmd/link/internal/loader"
-	"cmd/link/internal/sym"
 	"encoding/binary"
 	"fmt"
 	"os"
@@ -57,10 +56,10 @@
 //
 // Logging an error means that on exit cmd/link will delete any
 // output file and return a non-zero error code.
-func Errorf(s *sym.Symbol, format string, args ...interface{}) {
-	if s != nil {
-		format = s.Name + ": " + format
-	}
+//
+// TODO: remove. Use ctxt.Errof instead.
+// All remaining calls use nil as first arg.
+func Errorf(dummy *int, format string, args ...interface{}) {
 	format += "\n"
 	fmt.Fprintf(os.Stderr, format, args...)
 	afterErrorAction()
@@ -113,10 +112,3 @@
 	}
 	return false
 }
-
-// implements sort.Interface, for sorting symbols by name.
-type byName []*sym.Symbol
-
-func (s byName) Len() int           { return len(s) }
-func (s byName) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
-func (s byName) Less(i, j int) bool { return s[i].Name < s[j].Name }
diff --git a/src/cmd/link/internal/ld/xcoff.go b/src/cmd/link/internal/ld/xcoff.go
index 281747b..563fe49 100644
--- a/src/cmd/link/internal/ld/xcoff.go
+++ b/src/cmd/link/internal/ld/xcoff.go
@@ -10,6 +10,7 @@
 	"cmd/link/internal/loader"
 	"cmd/link/internal/sym"
 	"encoding/binary"
+	"fmt"
 	"io/ioutil"
 	"math/bits"
 	"path/filepath"
@@ -359,8 +360,7 @@
 
 // xcoffLoaderReloc holds information about a relocation made by the loader.
 type xcoffLoaderReloc struct {
-	sym    *sym.Symbol
-	sym2   loader.Sym
+	sym    loader.Sym
 	roff   int32
 	rtype  uint16
 	symndx int32
@@ -568,7 +568,7 @@
 
 // xcoffUpdateOuterSize stores the size of outer symbols in order to have it
 // in the symbol table.
-func xcoffUpdateOuterSize2(ctxt *Link, size int64, stype sym.SymKind) {
+func xcoffUpdateOuterSize(ctxt *Link, size int64, stype sym.SymKind) {
 	if size == 0 {
 		return
 	}
@@ -616,13 +616,13 @@
 }
 
 // xcoffAlign returns the log base 2 of the symbol's alignment.
-func xcoffAlign(x *sym.Symbol, t SymbolType) uint8 {
-	align := x.Align
+func xcoffAlign(ldr *loader.Loader, x loader.Sym, t SymbolType) uint8 {
+	align := ldr.SymAlign(x)
 	if align == 0 {
 		if t == TextSym {
 			align = int32(Funcalign)
 		} else {
-			align = symalign(x)
+			align = symalign(ldr, x)
 		}
 	}
 	return logBase2(int(align))
@@ -642,6 +642,7 @@
 // Currently, a new file is in fact a new package. It seems to be OK, but it might change
 // in the future.
 func (f *xcoffFile) writeSymbolNewFile(ctxt *Link, name string, firstEntry uint64, extnum int16) {
+	ldr := ctxt.loader
 	/* C_FILE */
 	s := &XcoffSymEnt64{
 		Noffset: uint32(f.stringTable.add(".file")),
@@ -670,8 +671,7 @@
 			dwsize = getDwsectCUSize(sect.Name, name)
 			// .debug_abbrev is common to all packages and not found with the previous function
 			if sect.Name == ".debug_abbrev" {
-				s := ctxt.Syms.ROLookup(sect.Name, 0)
-				dwsize = uint64(s.Size)
+				dwsize = uint64(ldr.SymSize(loader.Sym(sect.Sym)))
 
 			}
 		} else {
@@ -693,8 +693,7 @@
 			// Dwarf relocations need the symbol number of .dw* symbols.
 			// It doesn't need to know it for each package, one is enough.
 			// currSymSrcFile.csectAux == nil means first package.
-			dws := ctxt.Syms.Lookup(sect.Name, 0)
-			dws.Dynid = int32(f.symbolCount)
+			ldr.SetSymDynid(loader.Sym(sect.Sym), int32(f.symbolCount))
 
 			if sect.Name == ".debug_frame" && ctxt.LinkMode != LinkExternal {
 				// CIE size must be added to the first package.
@@ -774,28 +773,30 @@
 // Write symbol representing a .text function.
 // The symbol table is split with C_FILE corresponding to each package
 // and not to each source file as it should be.
-func (f *xcoffFile) writeSymbolFunc(ctxt *Link, x *sym.Symbol) []xcoffSym {
+func (f *xcoffFile) writeSymbolFunc(ctxt *Link, x loader.Sym) []xcoffSym {
 	// New XCOFF symbols which will be written.
 	syms := []xcoffSym{}
 
 	// Check if a new file is detected.
-	if strings.Contains(x.Name, "-tramp") || strings.HasPrefix(x.Name, "runtime.text.") {
+	ldr := ctxt.loader
+	name := ldr.SymName(x)
+	if strings.Contains(name, "-tramp") || strings.HasPrefix(name, "runtime.text.") {
 		// Trampoline don't have a FILE so there are considered
 		// in the current file.
 		// Same goes for runtime.text.X symbols.
-	} else if symPkg(ctxt, x) == "" { // Undefined global symbol
+	} else if ldr.SymPkg(x) == "" { // Undefined global symbol
 		// If this happens, the algorithm must be redone.
 		if currSymSrcFile.name != "" {
 			Exitf("undefined global symbol found inside another file")
 		}
 	} else {
 		// Current file has changed. New C_FILE, C_DWARF, etc must be generated.
-		if currSymSrcFile.name != symPkg(ctxt, x) {
+		if currSymSrcFile.name != ldr.SymPkg(x) {
 			if ctxt.LinkMode == LinkInternal {
 				// update previous file values
 				xfile.updatePreviousFile(ctxt, false)
-				currSymSrcFile.name = symPkg(ctxt, x)
-				f.writeSymbolNewFile(ctxt, symPkg(ctxt, x), uint64(x.Value), xfile.getXCOFFscnum(x.Sect))
+				currSymSrcFile.name = ldr.SymPkg(x)
+				f.writeSymbolNewFile(ctxt, ldr.SymPkg(x), uint64(ldr.SymValue(x)), xfile.getXCOFFscnum(ldr.SymSect(x)))
 			} else {
 				// With external linking, ld will crash if there is several
 				// .FILE and DWARF debugging enable, somewhere during
@@ -805,8 +806,8 @@
 				// TODO(aix); remove once ld has been fixed or the triggering
 				// relocation has been found and fixed.
 				if currSymSrcFile.name == "" {
-					currSymSrcFile.name = symPkg(ctxt, x)
-					f.writeSymbolNewFile(ctxt, "go_functions", uint64(x.Value), xfile.getXCOFFscnum(x.Sect))
+					currSymSrcFile.name = ldr.SymPkg(x)
+					f.writeSymbolNewFile(ctxt, "go_functions", uint64(ldr.SymValue(x)), xfile.getXCOFFscnum(ldr.SymSect(x)))
 				}
 			}
 
@@ -815,26 +816,26 @@
 
 	s := &XcoffSymEnt64{
 		Nsclass: C_EXT,
-		Noffset: uint32(xfile.stringTable.add(x.Extname())),
-		Nvalue:  uint64(x.Value),
-		Nscnum:  f.getXCOFFscnum(x.Sect),
+		Noffset: uint32(xfile.stringTable.add(ldr.SymExtname(x))),
+		Nvalue:  uint64(ldr.SymValue(x)),
+		Nscnum:  f.getXCOFFscnum(ldr.SymSect(x)),
 		Ntype:   SYM_TYPE_FUNC,
 		Nnumaux: 2,
 	}
 
-	if x.Version != 0 || x.Attr.VisibilityHidden() || x.Attr.Local() {
+	if ldr.SymVersion(x) != 0 || ldr.AttrVisibilityHidden(x) || ldr.AttrLocal(x) {
 		s.Nsclass = C_HIDEXT
 	}
 
-	x.Dynid = int32(xfile.symbolCount)
+	ldr.SetSymDynid(x, int32(xfile.symbolCount))
 	syms = append(syms, s)
 
 	// Update current csect size
-	currSymSrcFile.csectSize += x.Size
+	currSymSrcFile.csectSize += ldr.SymSize(x)
 
 	// create auxiliary entries
 	a2 := &XcoffAuxFcn64{
-		Xfsize:   uint32(x.Size),
+		Xfsize:   uint32(ldr.SymSize(x)),
 		Xlnnoptr: 0,                     // TODO
 		Xendndx:  xfile.symbolCount + 3, // this symbol + 2 aux entries
 		Xauxtype: _AUX_FCN,
@@ -848,44 +849,49 @@
 		Xsmtyp:    XTY_LD, // label definition (based on C)
 		Xauxtype:  _AUX_CSECT,
 	}
-	a4.Xsmtyp |= uint8(xcoffAlign(x, TextSym) << 3)
+	a4.Xsmtyp |= uint8(xcoffAlign(ldr, x, TextSym) << 3)
 
 	syms = append(syms, a4)
 	return syms
 }
 
 // put function used by genasmsym to write symbol table
-func putaixsym(ctxt *Link, x *sym.Symbol, str string, t SymbolType, addr int64) {
-
+func putaixsym(ctxt *Link, x loader.Sym, t SymbolType) {
 	// All XCOFF symbols generated by this GO symbols
 	// Can be a symbol entry or a auxiliary entry
 	syms := []xcoffSym{}
 
+	ldr := ctxt.loader
+	name := ldr.SymName(x)
+	if t == UndefinedSym {
+		name = ldr.SymExtname(x)
+	}
+
 	switch t {
 	default:
 		return
 
 	case TextSym:
-		if symPkg(ctxt, x) != "" || strings.Contains(x.Name, "-tramp") || strings.HasPrefix(x.Name, "runtime.text.") {
+		if ldr.SymPkg(x) != "" || strings.Contains(name, "-tramp") || strings.HasPrefix(name, "runtime.text.") {
 			// Function within a file
 			syms = xfile.writeSymbolFunc(ctxt, x)
 		} else {
 			// Only runtime.text and runtime.etext come through this way
-			if x.Name != "runtime.text" && x.Name != "runtime.etext" && x.Name != "go.buildid" {
-				Exitf("putaixsym: unknown text symbol %s", x.Name)
+			if name != "runtime.text" && name != "runtime.etext" && name != "go.buildid" {
+				Exitf("putaixsym: unknown text symbol %s", name)
 			}
 			s := &XcoffSymEnt64{
 				Nsclass: C_HIDEXT,
-				Noffset: uint32(xfile.stringTable.add(str)),
-				Nvalue:  uint64(x.Value),
-				Nscnum:  xfile.getXCOFFscnum(x.Sect),
+				Noffset: uint32(xfile.stringTable.add(name)),
+				Nvalue:  uint64(ldr.SymValue(x)),
+				Nscnum:  xfile.getXCOFFscnum(ldr.SymSect(x)),
 				Ntype:   SYM_TYPE_FUNC,
 				Nnumaux: 1,
 			}
-			x.Dynid = int32(xfile.symbolCount)
+			ldr.SetSymDynid(x, int32(xfile.symbolCount))
 			syms = append(syms, s)
 
-			size := uint64(x.Size)
+			size := uint64(ldr.SymSize(x))
 			a4 := &XcoffAuxCSect64{
 				Xauxtype:  _AUX_CSECT,
 				Xscnlenlo: uint32(size & 0xFFFFFFFF),
@@ -893,21 +899,20 @@
 				Xsmclas:   XMC_PR,
 				Xsmtyp:    XTY_SD,
 			}
-			a4.Xsmtyp |= uint8(xcoffAlign(x, TextSym) << 3)
+			a4.Xsmtyp |= uint8(xcoffAlign(ldr, x, TextSym) << 3)
 			syms = append(syms, a4)
-
 		}
 
 	case DataSym, BSSSym:
 		s := &XcoffSymEnt64{
 			Nsclass: C_EXT,
-			Noffset: uint32(xfile.stringTable.add(str)),
-			Nvalue:  uint64(x.Value),
-			Nscnum:  xfile.getXCOFFscnum(x.Sect),
+			Noffset: uint32(xfile.stringTable.add(name)),
+			Nvalue:  uint64(ldr.SymValue(x)),
+			Nscnum:  xfile.getXCOFFscnum(ldr.SymSect(x)),
 			Nnumaux: 1,
 		}
 
-		if x.Version != 0 || x.Attr.VisibilityHidden() || x.Attr.Local() {
+		if ldr.SymVersion(x) != 0 || ldr.AttrVisibilityHidden(x) || ldr.AttrLocal(x) {
 			// There is more symbols in the case of a global data
 			// which are related to the assembly generated
 			// to access such symbols.
@@ -917,7 +922,7 @@
 			s.Nsclass = C_HIDEXT
 		}
 
-		x.Dynid = int32(xfile.symbolCount)
+		ldr.SetSymDynid(x, int32(xfile.symbolCount))
 		syms = append(syms, s)
 
 		// Create auxiliary entry
@@ -926,15 +931,15 @@
 		// the data and bss symbols of one file/package.
 		// However, it's easier to just have a csect for each symbol.
 		// It might change
-		size := uint64(x.Size)
+		size := uint64(ldr.SymSize(x))
 		a4 := &XcoffAuxCSect64{
 			Xauxtype:  _AUX_CSECT,
 			Xscnlenlo: uint32(size & 0xFFFFFFFF),
 			Xscnlenhi: uint32(size >> 32),
 		}
 
-		if x.Type >= sym.STYPE && x.Type <= sym.SPCLNTAB {
-			if ctxt.LinkMode == LinkExternal && strings.HasPrefix(x.Sect.Name, ".data.rel.ro") {
+		if ty := ldr.SymType(x); ty >= sym.STYPE && ty <= sym.SPCLNTAB {
+			if ctxt.IsExternal() && strings.HasPrefix(ldr.SymSect(x).Name, ".data.rel.ro") {
 				// During external linking, read-only datas with relocation
 				// must be in .data.
 				a4.Xsmclas = XMC_RW
@@ -942,9 +947,9 @@
 				// Read only data
 				a4.Xsmclas = XMC_RO
 			}
-		} else if x.Type == sym.SDATA && strings.HasPrefix(x.Name, "TOC.") && ctxt.LinkMode == LinkExternal {
+		} else if /*ty == sym.SDATA &&*/ strings.HasPrefix(ldr.SymName(x), "TOC.") && ctxt.IsExternal() {
 			a4.Xsmclas = XMC_TC
-		} else if x.Name == "TOC" {
+		} else if ldr.SymName(x) == "TOC" {
 			a4.Xsmclas = XMC_TC0
 		} else {
 			a4.Xsmclas = XMC_RW
@@ -955,20 +960,20 @@
 			a4.Xsmtyp |= XTY_CM
 		}
 
-		a4.Xsmtyp |= uint8(xcoffAlign(x, t) << 3)
+		a4.Xsmtyp |= uint8(xcoffAlign(ldr, x, t) << 3)
 
 		syms = append(syms, a4)
 
 	case UndefinedSym:
-		if x.Type != sym.SDYNIMPORT && x.Type != sym.SHOSTOBJ && x.Type != sym.SUNDEFEXT {
+		if ty := ldr.SymType(x); ty != sym.SDYNIMPORT && ty != sym.SHOSTOBJ && ty != sym.SUNDEFEXT {
 			return
 		}
 		s := &XcoffSymEnt64{
 			Nsclass: C_EXT,
-			Noffset: uint32(xfile.stringTable.add(str)),
+			Noffset: uint32(xfile.stringTable.add(name)),
 			Nnumaux: 1,
 		}
-		x.Dynid = int32(xfile.symbolCount)
+		ldr.SetSymDynid(x, int32(xfile.symbolCount))
 		syms = append(syms, s)
 
 		a4 := &XcoffAuxCSect64{
@@ -977,7 +982,7 @@
 			Xsmtyp:   XTY_ER | XTY_IMP,
 		}
 
-		if x.Name == "__n_pthreads" {
+		if ldr.SymName(x) == "__n_pthreads" {
 			// Currently, all imported symbols made by cgo_import_dynamic are
 			// syscall functions, except __n_pthreads which is a variable.
 			// TODO(aix): Find a way to detect variables imported by cgo.
@@ -989,16 +994,16 @@
 	case TLSSym:
 		s := &XcoffSymEnt64{
 			Nsclass: C_EXT,
-			Noffset: uint32(xfile.stringTable.add(str)),
-			Nscnum:  xfile.getXCOFFscnum(x.Sect),
-			Nvalue:  uint64(x.Value),
+			Noffset: uint32(xfile.stringTable.add(name)),
+			Nscnum:  xfile.getXCOFFscnum(ldr.SymSect(x)),
+			Nvalue:  uint64(ldr.SymValue(x)),
 			Nnumaux: 1,
 		}
 
-		x.Dynid = int32(xfile.symbolCount)
+		ldr.SetSymDynid(x, int32(xfile.symbolCount))
 		syms = append(syms, s)
 
-		size := uint64(x.Size)
+		size := uint64(ldr.SymSize(x))
 		a4 := &XcoffAuxCSect64{
 			Xauxtype:  _AUX_CSECT,
 			Xsmclas:   XMC_UL,
@@ -1019,18 +1024,114 @@
 // It will be written in out file in Asmbxcoff, because it must be
 // at the very end, especially after relocation sections which needs symbols' index.
 func (f *xcoffFile) asmaixsym(ctxt *Link) {
+	ldr := ctxt.loader
 	// Get correct size for symbols wrapping others symbols like go.string.*
 	// sym.Size can be used directly as the symbols have already been written.
 	for name, size := range outerSymSize {
-		sym := ctxt.Syms.ROLookup(name, 0)
-		if sym == nil {
+		sym := ldr.Lookup(name, 0)
+		if sym == 0 {
 			Errorf(nil, "unknown outer symbol with name %s", name)
 		} else {
-			sym.Size = size
+			s := ldr.MakeSymbolUpdater(sym)
+			s.SetSize(size)
 		}
 	}
 
-	genasmsym(ctxt, putaixsym)
+	// These symbols won't show up in the first loop below because we
+	// skip sym.STEXT symbols. Normal sym.STEXT symbols are emitted by walking textp.
+	s := ldr.Lookup("runtime.text", 0)
+	if ldr.SymType(s) == sym.STEXT {
+		// We've already included this symbol in ctxt.Textp on AIX with external linker.
+		// See data.go:/textaddress
+		if !ctxt.IsExternal() {
+			putaixsym(ctxt, s, TextSym)
+		}
+	}
+
+	n := 1
+	// Generate base addresses for all text sections if there are multiple
+	for _, sect := range Segtext.Sections[1:] {
+		if sect.Name != ".text" || ctxt.IsExternal() {
+			// On AIX, runtime.text.X are symbols already in the symtab.
+			break
+		}
+		s = ldr.Lookup(fmt.Sprintf("runtime.text.%d", n), 0)
+		if s == 0 {
+			break
+		}
+		if ldr.SymType(s) == sym.STEXT {
+			putaixsym(ctxt, s, TextSym)
+		}
+		n++
+	}
+
+	s = ldr.Lookup("runtime.etext", 0)
+	if ldr.SymType(s) == sym.STEXT {
+		// We've already included this symbol in ctxt.Textp
+		// on AIX with external linker.
+		// See data.go:/textaddress
+		if !ctxt.IsExternal() {
+			putaixsym(ctxt, s, TextSym)
+		}
+	}
+
+	shouldBeInSymbolTable := func(s loader.Sym, name string) bool {
+		if name == ".go.buildinfo" {
+			// On AIX, .go.buildinfo must be in the symbol table as
+			// it has relocations.
+			return true
+		}
+		if ldr.AttrNotInSymbolTable(s) {
+			return false
+		}
+		if (name == "" || name[0] == '.') && !ldr.IsFileLocal(s) && name != ".TOC." {
+			return false
+		}
+		return true
+	}
+
+	for s, nsym := loader.Sym(1), loader.Sym(ldr.NSym()); s < nsym; s++ {
+		if !shouldBeInSymbolTable(s, ldr.SymName(s)) {
+			continue
+		}
+		st := ldr.SymType(s)
+		switch {
+		case st == sym.STLSBSS:
+			if ctxt.IsExternal() {
+				putaixsym(ctxt, s, TLSSym)
+			}
+
+		case st == sym.SBSS, st == sym.SNOPTRBSS, st == sym.SLIBFUZZER_EXTRA_COUNTER:
+			if ldr.AttrReachable(s) {
+				data := ldr.Data(s)
+				if len(data) > 0 {
+					ldr.Errorf(s, "should not be bss (size=%d type=%v special=%v)", len(data), ldr.SymType(s), ldr.AttrSpecial(s))
+				}
+				putaixsym(ctxt, s, BSSSym)
+			}
+
+		case st >= sym.SELFRXSECT && st < sym.SXREF: // data sections handled in dodata
+			if ldr.AttrReachable(s) {
+				putaixsym(ctxt, s, DataSym)
+			}
+
+		case st == sym.SUNDEFEXT:
+			putaixsym(ctxt, s, UndefinedSym)
+
+		case st == sym.SDYNIMPORT:
+			if ldr.AttrReachable(s) {
+				putaixsym(ctxt, s, UndefinedSym)
+			}
+		}
+	}
+
+	for _, s := range ctxt.Textp {
+		putaixsym(ctxt, s, TextSym)
+	}
+
+	if ctxt.Debugvlog != 0 || *flagN {
+		ctxt.Logf("symsize = %d\n", uint32(symSize))
+	}
 	xfile.updatePreviousFile(ctxt, true)
 }
 
@@ -1109,7 +1210,7 @@
 
 // Xcoffadddynrel adds a dynamic relocation in a XCOFF file.
 // This relocation will be made by the loader.
-func Xcoffadddynrel2(target *Target, ldr *loader.Loader, syms *ArchSyms, s loader.Sym, r loader.Reloc2, rIdx int) bool {
+func Xcoffadddynrel(target *Target, ldr *loader.Loader, syms *ArchSyms, s loader.Sym, r loader.Reloc2, rIdx int) bool {
 	if target.IsExternal() {
 		return true
 	}
@@ -1119,10 +1220,10 @@
 	}
 
 	xldr := &xcoffLoaderReloc{
-		sym2: s,
+		sym:  s,
 		roff: r.Off(),
 	}
-	targ := r.Sym()
+	targ := ldr.ResolveABIAlias(r.Sym())
 	var targType sym.SymKind
 	if targ != 0 {
 		targType = ldr.SymType(targ)
@@ -1264,6 +1365,7 @@
 		Lsymoff:  LDHDRSZ_64,
 	}
 
+	ldr := ctxt.loader
 	/* Symbol table */
 	for _, s := range f.loaderSymbols {
 		lds := &XcoffLdSym64{
@@ -1271,19 +1373,19 @@
 			Lsmtype: s.smtype,
 			Lsmclas: s.smclas,
 		}
-		sym := ctxt.loader.Syms[s.sym]
+		sym := s.sym
 		switch s.smtype {
 		default:
-			Errorf(sym, "unexpected loader symbol type: 0x%x", s.smtype)
+			ldr.Errorf(sym, "unexpected loader symbol type: 0x%x", s.smtype)
 		case XTY_ENT | XTY_SD:
-			lds.Lvalue = uint64(sym.Value)
-			lds.Lscnum = f.getXCOFFscnum(sym.Sect)
+			lds.Lvalue = uint64(ldr.SymValue(sym))
+			lds.Lscnum = f.getXCOFFscnum(ldr.SymSect(sym))
 		case XTY_IMP:
-			lds.Lifile = int32(f.dynLibraries[sym.Dynimplib()] + 1)
+			lds.Lifile = int32(f.dynLibraries[ldr.SymDynimplib(sym)] + 1)
 		}
 		ldstr := &XcoffLdStr64{
-			size: uint16(len(sym.Name) + 1), // + null terminator
-			name: sym.Name,
+			size: uint16(len(ldr.SymName(sym)) + 1), // + null terminator
+			name: ldr.SymName(sym),
 		}
 		stlen += uint32(2 + ldstr.size) // 2 = sizeof ldstr.size
 		symtab = append(symtab, lds)
@@ -1296,11 +1398,11 @@
 	off := hdr.Lrldoff                                // current offset is the same of reloc offset
 
 	/* Reloc */
-	ep := ctxt.Syms.ROLookup(*flagEntrySymbol, 0)
+	ep := ldr.Lookup(*flagEntrySymbol, 0)
 	xldr := &XcoffLdRel64{
-		Lvaddr:  uint64(ep.Value),
+		Lvaddr:  uint64(ldr.SymValue(ep)),
 		Lrtype:  0x3F00,
-		Lrsecnm: f.getXCOFFscnum(ep.Sect),
+		Lrsecnm: f.getXCOFFscnum(ldr.SymSect(ep)),
 		Lsymndx: 0,
 	}
 	off += 16
@@ -1309,17 +1411,17 @@
 	off += uint64(16 * len(f.loaderReloc))
 	for _, r := range f.loaderReloc {
 		symp := r.sym
-		if symp == nil {
-			symp = ctxt.loader.Syms[r.sym2]
+		if symp == 0 {
+			panic("unexpected 0 sym value")
 		}
 		xldr = &XcoffLdRel64{
-			Lvaddr:  uint64(symp.Value + int64(r.roff)),
+			Lvaddr:  uint64(ldr.SymValue(symp) + int64(r.roff)),
 			Lrtype:  r.rtype,
 			Lsymndx: r.symndx,
 		}
 
-		if symp.Sect != nil {
-			xldr.Lrsecnm = f.getXCOFFscnum(symp.Sect)
+		if ldr.SymSect(symp) != nil {
+			xldr.Lrsecnm = f.getXCOFFscnum(ldr.SymSect(symp))
 		}
 
 		reloctab = append(reloctab, xldr)
@@ -1416,6 +1518,7 @@
 	}
 
 	if ctxt.BuildMode == BuildModeExe && ctxt.LinkMode == LinkInternal {
+		ldr := ctxt.loader
 		f.xfhdr.Fopthdr = AOUTHSZ_EXEC64
 		f.xfhdr.Fflags = F_EXEC
 
@@ -1423,12 +1526,12 @@
 		f.xahdr.Ovstamp = 1 // based on dump -o
 		f.xahdr.Omagic = 0x10b
 		copy(f.xahdr.Omodtype[:], "1L")
-		entry := ctxt.Syms.ROLookup(*flagEntrySymbol, 0)
-		f.xahdr.Oentry = uint64(entry.Value)
-		f.xahdr.Osnentry = f.getXCOFFscnum(entry.Sect)
-		toc := ctxt.Syms.ROLookup("TOC", 0)
-		f.xahdr.Otoc = uint64(toc.Value)
-		f.xahdr.Osntoc = f.getXCOFFscnum(toc.Sect)
+		entry := ldr.Lookup(*flagEntrySymbol, 0)
+		f.xahdr.Oentry = uint64(ldr.SymValue(entry))
+		f.xahdr.Osnentry = f.getXCOFFscnum(ldr.SymSect(entry))
+		toc := ldr.Lookup("TOC", 0)
+		f.xahdr.Otoc = uint64(ldr.SymValue(toc))
+		f.xahdr.Osntoc = f.getXCOFFscnum(ldr.SymSect(toc))
 
 		f.xahdr.Oalgntext = int16(logBase2(int(Funcalign)))
 		f.xahdr.Oalgndata = 0x5
@@ -1453,7 +1556,11 @@
 }
 
 // Generate XCOFF assembly file
-func Asmbxcoff(ctxt *Link, fileoff int64) {
+func asmbXcoff(ctxt *Link) {
+	ctxt.Out.SeekSet(0)
+	fileoff := int64(Segdwarf.Fileoff + Segdwarf.Filelen)
+	fileoff = int64(Rnd(int64(fileoff), int64(*FlagRound)))
+
 	xfile.sectNameToScnum = make(map[string]int16)
 
 	// Add sections
@@ -1534,19 +1641,6 @@
 	xcoffwrite(ctxt)
 }
 
-// byOffset is used to sort relocations by offset
-type byOffset []sym.Reloc
-
-func (x byOffset) Len() int { return len(x) }
-
-func (x byOffset) Swap(i, j int) {
-	x[i], x[j] = x[j], x[i]
-}
-
-func (x byOffset) Less(i, j int) bool {
-	return x[i].Off < x[j].Off
-}
-
 // emitRelocations emits relocation entries for go.o in external linking.
 func (f *xcoffFile) emitRelocations(ctxt *Link, fileoff int64) {
 	ctxt.Out.SeekSet(fileoff)
@@ -1554,9 +1648,10 @@
 		ctxt.Out.Write8(0)
 	}
 
+	ldr := ctxt.loader
 	// relocsect relocates symbols from first in section sect, and returns
 	// the total number of relocations emitted.
-	relocsect := func(sect *sym.Section, syms []*sym.Symbol, base uint64) uint32 {
+	relocsect := func(sect *sym.Section, syms []loader.Sym, base uint64) uint32 {
 		// ctxt.Logf("%s 0x%x\n", sect.Name, sect.Vaddr)
 		// If main section has no bits, nothing to relocate.
 		if sect.Vaddr >= sect.Seg.Vaddr+sect.Seg.Filelen {
@@ -1564,42 +1659,45 @@
 		}
 		sect.Reloff = uint64(ctxt.Out.Offset())
 		for i, s := range syms {
-			if !s.Attr.Reachable() {
+			if !ldr.AttrReachable(s) {
 				continue
 			}
-			if uint64(s.Value) >= sect.Vaddr {
+			if uint64(ldr.SymValue(s)) >= sect.Vaddr {
 				syms = syms[i:]
 				break
 			}
 		}
 		eaddr := int64(sect.Vaddr + sect.Length)
 		for _, s := range syms {
-			if !s.Attr.Reachable() {
+			if !ldr.AttrReachable(s) {
 				continue
 			}
-			if s.Value >= int64(eaddr) {
+			if ldr.SymValue(s) >= int64(eaddr) {
 				break
 			}
 
-			// Relocation must be ordered by address, so s.R is ordered by Off.
-			sort.Sort(byOffset(s.R))
+			// Relocation must be ordered by address, so create a list of sorted indices.
+			relocs := ldr.ExtRelocs(s)
+			sorted := make([]int, relocs.Count())
+			for i := 0; i < relocs.Count(); i++ {
+				sorted[i] = i
+			}
+			sort.Slice(sorted, func(i, j int) bool {
+				return relocs.At(sorted[i]).Off() < relocs.At(sorted[j]).Off()
+			})
 
-			for ri := range s.R {
+			for _, ri := range sorted {
+				r := relocs.At(ri)
 
-				r := &s.R[ri]
-
-				if r.Done {
+				if r.Xsym == 0 {
+					ldr.Errorf(s, "missing xsym in relocation")
 					continue
 				}
-				if r.Xsym == nil {
-					Errorf(s, "missing xsym in relocation")
-					continue
+				if ldr.SymDynid(r.Xsym) < 0 {
+					ldr.Errorf(s, "reloc %s to non-coff symbol %s (outer=%s) %d %d", r.Type(), ldr.SymName(r.Sym()), ldr.SymName(r.Xsym), ldr.SymType(r.Sym()), ldr.SymDynid(r.Xsym))
 				}
-				if r.Xsym.Dynid < 0 {
-					Errorf(s, "reloc %s to non-coff symbol %s (outer=%s) %d %d", r.Type.String(), r.Sym.Name, r.Xsym.Name, r.Sym.Type, r.Xsym.Dynid)
-				}
-				if !thearch.Xcoffreloc1(ctxt.Arch, ctxt.Out, s, r, int64(uint64(s.Value+int64(r.Off))-base)) {
-					Errorf(s, "unsupported obj reloc %d(%s)/%d to %s", r.Type, r.Type.String(), r.Siz, r.Sym.Name)
+				if !thearch.Xcoffreloc1(ctxt.Arch, ctxt.Out, ldr, s, r, int64(uint64(ldr.SymValue(s)+int64(r.Off()))-base)) {
+					ldr.Errorf(s, "unsupported obj reloc %d(%s)/%d to %s", r.Type(), r.Type(), r.Siz(), ldr.SymName(r.Sym()))
 				}
 			}
 		}
@@ -1632,8 +1730,8 @@
 	for i := 0; i < len(Segdwarf.Sections); i++ {
 		sect := Segdwarf.Sections[i]
 		si := dwarfp[i]
-		if si.secSym() != sect.Sym ||
-			si.secSym().Sect != sect {
+		if si.secSym() != loader.Sym(sect.Sym) ||
+			ldr.SymSect(si.secSym()) != sect {
 			panic("inconsistency between dwarfp and Segdwarf")
 		}
 		for _, xcoffSect := range f.sections {
@@ -1655,17 +1753,16 @@
 	fname = filepath.Join(*flagTmpdir, "export_file.exp")
 	var buf bytes.Buffer
 
-	for _, s := range ctxt.loader.Syms {
-		if s == nil {
+	ldr := ctxt.loader
+	for s, nsym := loader.Sym(1), loader.Sym(ldr.NSym()); s < nsym; s++ {
+		if !ldr.AttrCgoExport(s) {
 			continue
 		}
-		if !s.Attr.CgoExport() {
+		extname := ldr.SymExtname(s)
+		if !strings.HasPrefix(extname, "._cgoexp_") {
 			continue
 		}
-		if !strings.HasPrefix(s.Extname(), "._cgoexp_") {
-			continue
-		}
-		if s.Version != 0 {
+		if ldr.SymVersion(s) != 0 {
 			continue // Only export version 0 symbols. See the comment in doxcoff.
 		}
 
@@ -1673,7 +1770,7 @@
 		// exported by cgo.
 		// The corresponding Go symbol is:
 		// _cgoexp_hashcode_symname.
-		name := strings.SplitN(s.Extname(), "_", 4)[3]
+		name := strings.SplitN(extname, "_", 4)[3]
 
 		buf.Write([]byte(name + "\n"))
 	}
@@ -1684,5 +1781,4 @@
 	}
 
 	return fname
-
 }
diff --git a/src/cmd/link/internal/ld/xcoff2.go b/src/cmd/link/internal/ld/xcoff2.go
deleted file mode 100644
index 27edbcb..0000000
--- a/src/cmd/link/internal/ld/xcoff2.go
+++ /dev/null
@@ -1,113 +0,0 @@
-// 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/objabi"
-	"cmd/link/internal/loader"
-	"cmd/link/internal/sym"
-)
-
-// Temporary dumping around for sym.Symbol version of helper
-// functions in xcoff.go, still being used for some archs/oses.
-// FIXME: get rid of this file when dodata() is completely
-// converted.
-
-// xcoffUpdateOuterSize stores the size of outer symbols in order to have it
-// in the symbol table.
-func xcoffUpdateOuterSize(ctxt *Link, size int64, stype sym.SymKind) {
-	if size == 0 {
-		return
-	}
-
-	switch stype {
-	default:
-		Errorf(nil, "unknown XCOFF outer symbol for type %s", stype.String())
-	case sym.SRODATA, sym.SRODATARELRO, sym.SFUNCTAB, sym.SSTRING:
-		// Nothing to do
-	case sym.STYPERELRO:
-		if ctxt.UseRelro() && (ctxt.BuildMode == BuildModeCArchive || ctxt.BuildMode == BuildModeCShared || ctxt.BuildMode == BuildModePIE) {
-			// runtime.types size must be removed, as it's a real symbol.
-			outerSymSize["typerel.*"] = size - ctxt.Syms.ROLookup("runtime.types", 0).Size
-			return
-		}
-		fallthrough
-	case sym.STYPE:
-		if !ctxt.DynlinkingGo() {
-			// runtime.types size must be removed, as it's a real symbol.
-			outerSymSize["type.*"] = size - ctxt.Syms.ROLookup("runtime.types", 0).Size
-		}
-	case sym.SGOSTRING:
-		outerSymSize["go.string.*"] = size
-	case sym.SGOFUNC:
-		if !ctxt.DynlinkingGo() {
-			outerSymSize["go.func.*"] = size
-		}
-	case sym.SGOFUNCRELRO:
-		outerSymSize["go.funcrel.*"] = size
-	case sym.SGCBITS:
-		outerSymSize["runtime.gcbits.*"] = size
-	case sym.SITABLINK:
-		outerSymSize["runtime.itablink"] = size
-
-	}
-}
-
-// Xcoffadddynrel adds a dynamic relocation in a XCOFF file.
-// This relocation will be made by the loader.
-func Xcoffadddynrel(target *Target, ldr *loader.Loader, s *sym.Symbol, r *sym.Reloc) bool {
-	if target.IsExternal() {
-		return true
-	}
-	if s.Type <= sym.SPCLNTAB {
-		Errorf(s, "cannot have a relocation to %s in a text section symbol", r.Sym.Name)
-		return false
-	}
-
-	xldr := &xcoffLoaderReloc{
-		sym:  s,
-		roff: r.Off,
-	}
-
-	switch r.Type {
-	default:
-		Errorf(s, "unexpected .loader relocation to symbol: %s (type: %s)", r.Sym.Name, r.Type.String())
-		return false
-	case objabi.R_ADDR:
-		if s.Type == sym.SXCOFFTOC && r.Sym.Type == sym.SDYNIMPORT {
-			// Imported symbol relocation
-			for i, dynsym := range xfile.loaderSymbols {
-				if ldr.Syms[dynsym.sym].Name == r.Sym.Name {
-					xldr.symndx = int32(i + 3) // +3 because of 3 section symbols
-					break
-				}
-			}
-		} else if s.Type == sym.SDATA || s.Type == sym.SNOPTRDATA || s.Type == sym.SBUILDINFO || s.Type == sym.SXCOFFTOC {
-			switch r.Sym.Sect.Seg {
-			default:
-				Errorf(s, "unknown segment for .loader relocation with symbol %s", r.Sym.Name)
-			case &Segtext:
-			case &Segrodata:
-				xldr.symndx = 0 // .text
-			case &Segdata:
-				if r.Sym.Type == sym.SBSS || r.Sym.Type == sym.SNOPTRBSS {
-					xldr.symndx = 2 // .bss
-				} else {
-					xldr.symndx = 1 // .data
-				}
-
-			}
-
-		} else {
-			Errorf(s, "unexpected type for .loader relocation R_ADDR for symbol %s: %s to %s", r.Sym.Name, s.Type, r.Sym.Type)
-			return false
-		}
-
-		xldr.rtype = 0x3F<<8 + XCOFF_R_POS
-	}
-
-	xfile.loaderReloc = append(xfile.loaderReloc, xldr)
-	return true
-}
diff --git a/src/cmd/link/internal/loader/loader.go b/src/cmd/link/internal/loader/loader.go
index 32c342e..f87776e 100644
--- a/src/cmd/link/internal/loader/loader.go
+++ b/src/cmd/link/internal/loader/loader.go
@@ -33,7 +33,7 @@
 type Relocs struct {
 	rs []goobj2.Reloc
 
-	li int      // local index of symbol whose relocs we're examining
+	li uint32   // local index of symbol whose relocs we're examining
 	r  *oReader // object reader for containing package
 	l  *Loader  // loader
 }
@@ -125,12 +125,12 @@
 
 // objSym represents a symbol in an object file. It is a tuple of
 // the object and the symbol's local index.
-// For external symbols, r is l.extReader, s is its index into the
-// payload array.
-// {nil, 0} represents the nil symbol.
+// For external symbols, objidx is the index of l.extReader (extObj),
+// s is its index into the payload array.
+// {0, 0} represents the nil symbol.
 type objSym struct {
-	r *oReader
-	s int // local index
+	objidx uint32 // index of the object (in l.objs array)
+	s      uint32 // local index
 }
 
 type nameVer struct {
@@ -202,13 +202,6 @@
 //   extending the external symbol index space range. The host object
 //   loader stores symbol payloads in loader.payloads using SymbolBuilder.
 //
-// - For now, in loader.LoadFull we convert all symbols (Go + external)
-//   to sym.Symbols.
-//
-// - At some point (when the wayfront is pushed through all of the
-//   linker), all external symbols will be payload-based, and we can
-//   get rid of the loader.Syms array.
-//
 // - Each symbol gets a unique global index. For duplicated and
 //   overwriting/overwritten symbols, the second (or later) appearance
 //   of the symbol gets the same global index as the first appearance.
@@ -241,9 +234,6 @@
 
 	objByPkg map[string]*oReader // map package path to its Go object reader
 
-	Syms     []*sym.Symbol // indexed symbols. XXX we still make sym.Symbol for now.
-	symBatch []sym.Symbol  // batch of symbols.
-
 	anonVersion int // most recently assigned ext static sym pseudo-version
 
 	// Bitmaps and other side structures used to store data used to store
@@ -293,9 +283,6 @@
 	// the symbol that triggered the marking of symbol K as live.
 	Reachparent []Sym
 
-	relocBatch    []sym.Reloc    // for bulk allocation of relocations
-	relocExtBatch []sym.RelocExt // for bulk allocation of relocations
-
 	flags uint32
 
 	strictDupMsgs int // number of strict-dup warning/errors, when FlagStrictDups is enabled
@@ -303,8 +290,6 @@
 	elfsetstring elfsetstringFunc
 
 	errorReporter *ErrorReporter
-
-	SymLookup func(name string, ver int) *sym.Symbol
 }
 
 const (
@@ -313,7 +298,14 @@
 	nonPkgRef
 )
 
-type elfsetstringFunc func(s *sym.Symbol, str string, off int)
+// objidx
+const (
+	nilObj = iota
+	extObj
+	goObjStart
+)
+
+type elfsetstringFunc func(str string, off int)
 
 // extSymPayload holds the payload (data + relocations) for linker-synthesized
 // external symbols (note that symbol value is stored in a separate slice).
@@ -323,7 +315,6 @@
 	ver      int
 	kind     sym.SymKind
 	objidx   uint32 // index of original object if sym made by cloneToExternal
-	gotype   Sym    // Gotype (0 if not present)
 	relocs   []goobj2.Reloc
 	reltypes []objabi.RelocType // relocation types
 	data     []byte
@@ -337,11 +328,12 @@
 
 func NewLoader(flags uint32, elfsetstring elfsetstringFunc, reporter *ErrorReporter) *Loader {
 	nbuiltin := goobj2.NBuiltin()
+	extReader := &oReader{objidx: extObj}
 	ldr := &Loader{
 		start:                make(map[*oReader]Sym),
-		objs:                 []objIdx{{}}, // reserve index 0 for nil symbol
-		objSyms:              []objSym{{}}, // reserve index 0 for nil symbol
-		extReader:            &oReader{},
+		objs:                 []objIdx{{}, {extReader, 0}}, // reserve index 0 for nil symbol, 1 for external symbols
+		objSyms:              make([]objSym, 1, 100000),    // reserve index 0 for nil symbol
+		extReader:            extReader,
 		symsByName:           [2]map[string]Sym{make(map[string]Sym, 100000), make(map[string]Sym, 50000)}, // preallocate ~2MB for ABI0 and ~1MB for ABI1 symbols
 		objByPkg:             make(map[string]*oReader),
 		outer:                make(map[Sym]Sym),
@@ -392,13 +384,13 @@
 
 // Add a symbol from an object file, return the global index and whether it is added.
 // If the symbol already exist, it returns the index of that symbol.
-func (l *Loader) AddSym(name string, ver int, r *oReader, li int, kind int, dupok bool, typ sym.SymKind) (Sym, bool) {
+func (l *Loader) AddSym(name string, ver int, r *oReader, li uint32, kind int, dupok bool, typ sym.SymKind) (Sym, bool) {
 	if l.extStart != 0 {
 		panic("AddSym called after external symbol is created")
 	}
 	i := Sym(len(l.objSyms))
 	addToGlobal := func() {
-		l.objSyms = append(l.objSyms, objSym{r, li})
+		l.objSyms = append(l.objSyms, objSym{r.objidx, li})
 	}
 	if name == "" {
 		addToGlobal()
@@ -448,7 +440,7 @@
 		if !(oldtyp.IsData() && oldr.DataSize(oldli) == 0) {
 			log.Fatalf("duplicated definition of symbol " + name)
 		}
-		l.objSyms[oldi] = objSym{r, li}
+		l.objSyms[oldi] = objSym{r.objidx, li}
 	} else {
 		// old symbol overwrites new symbol.
 		if !typ.IsData() { // only allow overwriting data symbol
@@ -465,9 +457,10 @@
 	if l.extStart == 0 {
 		l.extStart = i
 	}
-	l.growSyms(int(i))
+	l.growValues(int(i) + 1)
+	l.growAttrBitmaps(int(i) + 1)
 	pi := l.newPayload(name, ver)
-	l.objSyms = append(l.objSyms, objSym{l.extReader, int(pi)})
+	l.objSyms = append(l.objSyms, objSym{l.extReader.objidx, uint32(pi)})
 	l.extReader.syms = append(l.extReader.syms, i)
 	return i
 }
@@ -556,25 +549,14 @@
 	ms.data = ms.data[:siz]
 }
 
-// Ensure Syms slice has enough space.
-func (l *Loader) growSyms(i int) {
-	n := len(l.Syms)
-	if n > i {
-		return
-	}
-	l.Syms = append(l.Syms, make([]*sym.Symbol, i+1-n)...)
-	l.growValues(int(i) + 1)
-	l.growAttrBitmaps(int(i) + 1)
-}
-
 // Convert a local index to a global index.
-func (l *Loader) toGlobal(r *oReader, i int) Sym {
+func (l *Loader) toGlobal(r *oReader, i uint32) Sym {
 	return r.syms[i]
 }
 
 // Convert a global index to a local index.
-func (l *Loader) toLocal(i Sym) (*oReader, int) {
-	return l.objSyms[i].r, int(l.objSyms[i].s)
+func (l *Loader) toLocal(i Sym) (*oReader, uint32) {
+	return l.objs[l.objSyms[i].objidx].r, l.objSyms[i].s
 }
 
 // Resolve a local symbol reference. Return global index.
@@ -607,7 +589,7 @@
 			log.Fatalf("reference of nonexisted package %s, from %v", pkg, r.unit.Lib)
 		}
 	}
-	return l.toGlobal(rr, int(s.SymIdx))
+	return l.toGlobal(rr, s.SymIdx)
 }
 
 // Look up a symbol by name, return global index, or 0 if not found.
@@ -621,7 +603,7 @@
 }
 
 // Check that duplicate symbols have same contents.
-func (l *Loader) checkdup(name string, r *oReader, li int, dup Sym) {
+func (l *Loader) checkdup(name string, r *oReader, li uint32, dup Sym) {
 	p := r.Data(li)
 	rdup, ldup := l.toLocal(dup)
 	pdup := rdup.Data(ldup)
@@ -681,7 +663,11 @@
 		return pp.name
 	}
 	r, li := l.toLocal(i)
-	return strings.Replace(r.Sym(li).Name(r.Reader), "\"\".", r.pkgprefix, -1)
+	name := r.Sym(li).Name(r.Reader)
+	if !r.NeedNameExpansion() {
+		return name
+	}
+	return strings.Replace(name, "\"\".", r.pkgprefix, -1)
 }
 
 // Returns the version of the i-th symbol.
@@ -694,6 +680,8 @@
 	return int(abiToVer(r.Sym(li).ABI(), r.version))
 }
 
+func (l *Loader) IsFileLocal(i Sym) bool { return l.SymVersion(i) >= sym.SymVerStatic }
+
 // Returns the type of the i-th symbol.
 func (l *Loader) SymType(i Sym) sym.SymKind {
 	if l.IsExternal(i) {
@@ -861,7 +849,7 @@
 		// might make more sense to copy the flag value out of the
 		// object into a larger bitmap during preload.
 		r, _ := l.toLocal(i)
-		return (r.Flags() & goobj2.ObjFlagShared) != 0
+		return r.Shared()
 	}
 	return l.attrShared.Has(l.extIndex(i))
 }
@@ -1190,7 +1178,7 @@
 	return l.sects[l.symSects[i]]
 }
 
-// SetSymValue sets the section of the i-th symbol. i is global index.
+// SetSymSect sets the section of the i-th symbol. i is global index.
 func (l *Loader) SetSymSect(i Sym, sect *sym.Section) {
 	if int(i) >= len(l.symSects) {
 		l.symSects = append(l.symSects, make([]uint16, l.NSym()-len(l.symSects))...)
@@ -1420,12 +1408,17 @@
 // results in to a map (might want to try this at some point and see
 // if it helps speed things up).
 func (l *Loader) SymGoType(i Sym) Sym {
+	var r *oReader
+	var auxs []goobj2.Aux
 	if l.IsExternal(i) {
 		pp := l.getPayload(i)
-		return pp.gotype
+		r = l.objs[pp.objidx].r
+		auxs = pp.auxs
+	} else {
+		var li uint32
+		r, li = l.toLocal(i)
+		auxs = r.Auxs(li)
 	}
-	r, li := l.toLocal(i)
-	auxs := r.Auxs(li)
 	for j := range auxs {
 		a := &auxs[j]
 		switch a.Type() {
@@ -1546,7 +1539,7 @@
 		switch a.Type() {
 		case goobj2.AuxDwarfInfo:
 			auxDwarfInfo = l.resolve(r, a.Sym())
-			if l.SymType(auxDwarfInfo) != sym.SDWARFINFO {
+			if l.SymType(auxDwarfInfo) != sym.SDWARFFCN {
 				panic("aux dwarf info sym with wrong type")
 			}
 		case goobj2.AuxDwarfLoc:
@@ -1608,6 +1601,11 @@
 func (l *Loader) SetOuterSym(i Sym, o Sym) {
 	if o != 0 {
 		l.outer[i] = o
+		// relocsym's foldSubSymbolOffset requires that we only
+		// have a single level of containment-- enforce here.
+		if l.outer[o] != 0 {
+			panic("multiply nested outer sym")
+		}
 	} else {
 		delete(l.outer, i)
 	}
@@ -1703,7 +1701,7 @@
 }
 
 // Relocs returns a Relocs object given a local sym index and reader.
-func (l *Loader) relocs(r *oReader, li int) Relocs {
+func (l *Loader) relocs(r *oReader, li uint32) Relocs {
 	var rs []goobj2.Reloc
 	if l.isExtReader(r) {
 		pp := l.payloads[li]
@@ -1895,14 +1893,14 @@
 		r = l.objs[pp.objidx].r
 		auxs = pp.auxs
 	} else {
-		var li int
+		var li uint32
 		r, li = l.toLocal(i)
 		auxs = r.Auxs(li)
 	}
 	for j := range auxs {
 		a := &auxs[j]
 		if a.Type() == goobj2.AuxFuncInfo {
-			b := r.Data(int(a.Sym().SymIdx))
+			b := r.Data(a.Sym().SymIdx)
 			return FuncInfo{l, r, b, auxs, goobj2.FuncInfoLengths{}}
 		}
 	}
@@ -1913,7 +1911,7 @@
 // Does not add non-package symbols yet, which will be done in LoadNonpkgSyms.
 // Does not read symbol data.
 // Returns the fingerprint of the object.
-func (l *Loader) Preload(syms *sym.Symbols, f *bio.Reader, lib *sym.Library, unit *sym.CompilationUnit, length int64) goobj2.FingerprintType {
+func (l *Loader) Preload(localSymVersion int, f *bio.Reader, lib *sym.Library, unit *sym.CompilationUnit, length int64) goobj2.FingerprintType {
 	roObject, readonly, err := f.Slice(uint64(length)) // TODO: no need to map blocks that are for tools only (e.g. RefName)
 	if err != nil {
 		log.Fatal("cannot read object file:", err)
@@ -1921,11 +1919,10 @@
 	r := goobj2.NewReaderFromBytes(roObject, readonly)
 	if r == nil {
 		if len(roObject) >= 8 && bytes.Equal(roObject[:8], []byte("\x00go114ld")) {
-			log.Fatalf("found object file %s in old format, but -go115newobj is true\nset -go115newobj consistently in all -gcflags, -asmflags, and -ldflags", f.File().Name())
+			log.Fatalf("found object file %s in old format", f.File().Name())
 		}
 		panic("cannot read object file")
 	}
-	localSymVersion := syms.IncVersion()
 	pkgprefix := objabi.PathToPrefix(lib.Pkg) + "."
 	ndef := r.NSym()
 	nnonpkgdef := r.NNonpkgdef()
@@ -1952,9 +1949,9 @@
 
 // Preload symbols of given kind from an object.
 func (l *Loader) preloadSyms(r *oReader, kind int) {
-	ndef := r.NSym()
-	nnonpkgdef := r.NNonpkgdef()
-	var start, end int
+	ndef := uint32(r.NSym())
+	nnonpkgdef := uint32(r.NNonpkgdef())
+	var start, end uint32
 	switch kind {
 	case pkgDef:
 		start = 0
@@ -1965,11 +1962,14 @@
 	default:
 		panic("preloadSyms: bad kind")
 	}
-	l.growSyms(len(l.objSyms) + end - start)
-	l.growAttrBitmaps(len(l.objSyms) + end - start)
+	l.growAttrBitmaps(len(l.objSyms) + int(end-start))
+	needNameExpansion := r.NeedNameExpansion()
 	for i := start; i < end; i++ {
 		osym := r.Sym(i)
-		name := strings.Replace(osym.Name(r.Reader), "\"\".", r.pkgprefix, -1)
+		name := osym.Name(r.Reader)
+		if needNameExpansion {
+			name = strings.Replace(name, "\"\".", r.pkgprefix, -1)
+		}
 		v := abiToVer(osym.ABI(), r.version)
 		dupok := osym.Dupok()
 		gi, added := l.AddSym(name, v, r, i, kind, dupok, sym.AbiSymKindToSymKind[objabi.SymKind(osym.Type())])
@@ -1992,11 +1992,6 @@
 				l.builtinSyms[bi] = gi
 			}
 		}
-		if strings.HasPrefix(name, "go.string.") ||
-			strings.HasPrefix(name, "gclocals·") ||
-			strings.HasPrefix(name, "runtime.gcbits.") {
-			l.SetAttrNotInSymbolTable(gi, true)
-		}
 		if a := osym.Align(); a != 0 {
 			l.SetSymAlign(gi, int32(a))
 		}
@@ -2006,19 +2001,24 @@
 // Add non-package symbols and references to external symbols (which are always
 // named).
 func (l *Loader) LoadNonpkgSyms(arch *sys.Arch) {
-	for _, o := range l.objs[1:] {
+	for _, o := range l.objs[goObjStart:] {
 		l.preloadSyms(o.r, nonPkgDef)
 	}
-	for _, o := range l.objs[1:] {
+	for _, o := range l.objs[goObjStart:] {
 		loadObjRefs(l, o.r, arch)
 	}
+	l.values = make([]int64, l.NSym(), l.NSym()+1000) // +1000 make some room for external symbols
 }
 
 func loadObjRefs(l *Loader, r *oReader, arch *sys.Arch) {
-	ndef := r.NSym() + r.NNonpkgdef()
-	for i, n := 0, r.NNonpkgref(); i < n; i++ {
+	ndef := uint32(r.NSym() + r.NNonpkgdef())
+	needNameExpansion := r.NeedNameExpansion()
+	for i, n := uint32(0), uint32(r.NNonpkgref()); i < n; i++ {
 		osym := r.Sym(ndef + i)
-		name := strings.Replace(osym.Name(r.Reader), "\"\".", r.pkgprefix, -1)
+		name := osym.Name(r.Reader)
+		if needNameExpansion {
+			name = strings.Replace(name, "\"\".", r.pkgprefix, -1)
+		}
 		v := abiToVer(osym.ABI(), r.version)
 		r.syms[ndef+i] = l.LookupOrCreateSym(name, v)
 		gi := r.syms[ndef+i]
@@ -2070,163 +2070,6 @@
 	}
 }
 
-// Load full contents.
-func (l *Loader) LoadFull(arch *sys.Arch, syms *sym.Symbols, needReloc, needExtReloc bool) {
-	// create all Symbols first.
-	l.growSyms(l.NSym())
-	l.growSects(l.NSym())
-
-	if needReloc && len(l.extRelocs) != 0 {
-		// If needReloc is true, we are going to convert the loader's
-		// "internal" relocations to sym.Relocs. In this case, external
-		// relocations shouldn't be used.
-		panic("phase error")
-	}
-
-	nr := 0 // total number of sym.Reloc's we'll need
-	for _, o := range l.objs[1:] {
-		nr += loadObjSyms(l, syms, o.r, needReloc, needExtReloc)
-	}
-
-	// Make a first pass through the external symbols, making
-	// sure that each external symbol has a non-nil entry in
-	// l.Syms (note that relocations and symbol content will
-	// be copied in a later loop).
-	toConvert := make([]Sym, 0, len(l.payloads))
-	for _, i := range l.extReader.syms {
-		if !l.attrReachable.Has(i) {
-			continue
-		}
-		pp := l.getPayload(i)
-		if needReloc {
-			nr += len(pp.relocs)
-		}
-		if needExtReloc && int(i) < len(l.extRelocs) {
-			nr += len(l.extRelocs[i])
-		}
-		// create and install the sym.Symbol here so that l.Syms will
-		// be fully populated when we do relocation processing and
-		// outer/sub processing below. Note that once we do this,
-		// we'll need to get at the payload for a symbol with direct
-		// reference to l.payloads[] as opposed to calling l.getPayload().
-		s := l.allocSym(pp.name, 0)
-		l.installSym(i, s)
-		toConvert = append(toConvert, i)
-	}
-
-	// allocate a single large slab of relocations for all live symbols
-	if nr != 0 {
-		l.relocBatch = make([]sym.Reloc, nr)
-		if needExtReloc {
-			l.relocExtBatch = make([]sym.RelocExt, nr)
-		}
-	}
-
-	// convert payload-based external symbols into sym.Symbol-based
-	for _, i := range toConvert {
-
-		// Copy kind/size/value etc.
-		pp := l.payloads[l.extIndex(i)]
-		s := l.Syms[i]
-		s.Version = int16(pp.ver)
-		s.Type = pp.kind
-		s.Size = pp.size
-
-		// Copy relocations
-		if needReloc {
-			batch := l.relocBatch
-			s.R = batch[:len(pp.relocs):len(pp.relocs)]
-			l.relocBatch = batch[len(pp.relocs):]
-			relocs := l.Relocs(i)
-			l.convertRelocations(i, &relocs, s, false)
-		}
-		if needExtReloc {
-			l.convertExtRelocs(s, i)
-		}
-
-		// Copy data
-		s.P = pp.data
-
-		// Transfer over attributes.
-		l.migrateAttributes(i, s)
-	}
-
-	// load contents of defined symbols
-	for _, o := range l.objs[1:] {
-		loadObjFull(l, o.r, needReloc, needExtReloc)
-	}
-
-	// Sanity check: we should have consumed all batched allocations.
-	if len(l.relocBatch) != 0 || len(l.relocExtBatch) != 0 {
-		panic("batch allocation mismatch")
-	}
-
-	// Note: resolution of ABI aliases is now also handled in
-	// loader.convertRelocations, so once the host object loaders move
-	// completely to loader.Sym, we can remove the code below.
-
-	// Resolve ABI aliases for external symbols. This is only
-	// needed for internal cgo linking.
-	if needReloc {
-		for _, i := range l.extReader.syms {
-			if s := l.Syms[i]; s != nil && s.Attr.Reachable() {
-				for ri := range s.R {
-					r := &s.R[ri]
-					if r.Sym != nil && r.Sym.Type == sym.SABIALIAS {
-						r.Sym = r.Sym.R[0].Sym
-					}
-				}
-			}
-		}
-	}
-
-	// Free some memory.
-	// At this point we still need basic index mapping, and some fields of
-	// external symbol payloads, but not much else.
-	l.values = nil
-	l.symSects = nil
-	l.outdata = nil
-	l.itablink = nil
-	l.attrOnList = nil
-	l.attrLocal = nil
-	l.attrNotInSymbolTable = nil
-	l.attrVisibilityHidden = nil
-	l.attrDuplicateOK = nil
-	l.attrShared = nil
-	l.attrExternal = nil
-	l.attrReadOnly = nil
-	l.attrTopFrame = nil
-	l.attrSpecial = nil
-	l.attrCgoExportDynamic = nil
-	l.attrCgoExportStatic = nil
-	l.outer = nil
-	l.align = nil
-	l.dynimplib = nil
-	l.dynimpvers = nil
-	l.localentry = nil
-	l.extname = nil
-	l.elfType = nil
-	l.plt = nil
-	l.got = nil
-	l.dynid = nil
-	if needExtReloc { // converted to sym.Relocs, drop loader references
-		l.relocVariant = nil
-		l.extRelocs = nil
-	}
-
-	// Drop fields that are no longer needed.
-	for _, i := range l.extReader.syms {
-		pp := l.getPayload(i)
-		pp.name = ""
-		pp.auxs = nil
-		pp.data = nil
-		if needExtReloc {
-			pp.relocs = nil
-			pp.reltypes = nil
-		}
-	}
-}
-
 // ResolveABIAlias given a symbol returns the ABI alias target of that
 // symbol. If the sym in question is not an alias, the sym itself is
 // returned.
@@ -2245,227 +2088,6 @@
 	return target
 }
 
-// PropagateSymbolChangesBackToLoader is a temporary shim function
-// that copies over a given sym.Symbol into the equivalent representation
-// in the loader world. The intent is to enable converting a given
-// linker phase/pass from dealing with sym.Symbol's to a modernized
-// pass that works with loader.Sym, in cases where the "loader.Sym
-// wavefront" has not yet reached the pass in question. For such work
-// the recipe is to first call PropagateSymbolChangesBackToLoader(),
-// then exexute the pass working with the loader, then call
-// PropagateLoaderChangesToSymbols to copy the changes made by the
-// pass back to the sym.Symbol world.
-func (l *Loader) PropagateSymbolChangesBackToLoader() {
-
-	// For the moment we only copy symbol values, and we don't touch
-	// any new sym.Symbols created since loadlibfull() was run. This
-	// seems to be what's needed for DWARF gen.
-	for i := Sym(1); i < Sym(len(l.objSyms)); i++ {
-		s := l.Syms[i]
-		if s != nil {
-			if s.Value != l.SymValue(i) {
-				l.SetSymValue(i, s.Value)
-			}
-		}
-	}
-}
-
-// PropagateLoaderChangesToSymbols is a temporary shim function that
-// takes a list of loader.Sym symbols and works to copy their contents
-// and attributes over to a corresponding sym.Symbol. The parameter
-// anonVerReplacement specifies a version number for any new anonymous
-// symbols encountered on the list, when creating sym.Symbols for them
-// (or zero if we don't expect to encounter any new anon symbols). See
-// the PropagateSymbolChangesBackToLoader header comment for more
-// info.
-//
-// WARNING: this function is brittle and depends heavily on loader
-// implementation. A key problem with doing this is that as things
-// stand at the moment, some sym.Symbol contents/attributes are
-// populated only when converting from loader.Sym to sym.Symbol in
-// loadlibfull, meaning we may wipe out some information when copying
-// back.
-
-func (l *Loader) PropagateLoaderChangesToSymbols(toconvert []Sym, anonVerReplacement int) []*sym.Symbol {
-
-	result := []*sym.Symbol{}
-	relocfixup := []Sym{}
-
-	// Note: this loop needs to allow for the possibility that we may
-	// see "new" symbols on the 'toconvert' list that come from object
-	// files (for example, DWARF location lists), as opposed to just
-	// newly manufactured symbols (ex: DWARF section symbols such as
-	// ".debug_info").  This means that we have to be careful not to
-	// stomp on sym.Symbol attributes/content that was set up in
-	// in loadlibfull().
-
-	// Also note that in order for the relocation fixup to work, we
-	// have to do this in two passes -- one pass to create the symbols,
-	// and then a second fix up the relocations once all necessary
-	// sym.Symbols are created.
-
-	// First pass, symbol creation and symbol data fixup.
-	for _, cand := range toconvert {
-
-		sn := l.SymName(cand)
-		sv := l.SymVersion(cand)
-		st := l.SymType(cand)
-		if sv < 0 {
-			if anonVerReplacement == 0 {
-				panic("expected valid anon version replacement")
-			}
-			sv = anonVerReplacement
-		}
-
-		s := l.Syms[cand]
-
-		isnew := false
-		if sn == "" {
-			// Don't install anonymous symbols in the lookup tab.
-			if s == nil {
-				s = l.allocSym(sn, sv)
-				l.installSym(cand, s)
-			}
-			isnew = true
-		} else {
-			if s != nil {
-				// Already have a symbol for this -- it must be
-				// something that was previously processed by
-				// loadObjFull. Note that the symbol in question may
-				// or may not be in the name lookup map.
-			} else {
-				isnew = true
-				s = l.SymLookup(sn, sv)
-			}
-		}
-		result = append(result, s)
-
-		// Always copy these from new to old.
-		s.Value = l.SymValue(cand)
-		s.Type = st
-
-		// If the data for a symbol has increased in size, make sure
-		// we bring the new content across.
-		relfix := isnew
-		if isnew || len(l.Data(cand)) > len(s.P) {
-			s.P = l.Data(cand)
-			s.Size = int64(len(s.P))
-			relfix = true
-		}
-
-		// For 'new' symbols, copy other content.
-		if relfix {
-			relocfixup = append(relocfixup, cand)
-		}
-
-		// If new symbol, call a helper to migrate attributes.
-		// Otherwise touch only not-in-symbol-table, since there are
-		// some attrs that are only set up at the point where we
-		// convert loader.Sym to sym.Symbol.
-		if isnew {
-			l.migrateAttributes(cand, s)
-		} else {
-			if l.AttrNotInSymbolTable(cand) {
-				s.Attr.Set(sym.AttrNotInSymbolTable, true)
-			}
-		}
-	}
-
-	// Second pass to fix up relocations.
-	for _, cand := range relocfixup {
-		s := l.Syms[cand]
-		relocs := l.Relocs(cand)
-		if len(s.R) != relocs.Count() {
-			s.R = make([]sym.Reloc, relocs.Count())
-		}
-		l.convertRelocations(cand, &relocs, s, true)
-	}
-
-	return result
-}
-
-// ExtractSymbols grabs the symbols out of the loader for work that hasn't been
-// ported to the new symbol type.
-func (l *Loader) ExtractSymbols(syms *sym.Symbols) {
-	// 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. We do, however,
-	// add these symbols to the list of global symbols so that other future
-	// steps (like pclntab generation) can find these symbols if neceassary.
-	// 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 {
-			continue
-		}
-		if s.Version < 0 {
-			s.Version = int16(anonVerReplacement)
-		}
-	}
-
-	// Provide lookup functions for sym.Symbols.
-	l.SymLookup = func(name string, ver int) *sym.Symbol {
-		i := l.LookupOrCreateSym(name, ver)
-		if s := l.Syms[i]; s != nil {
-			return s
-		}
-		s := l.allocSym(name, ver)
-		l.installSym(i, s)
-		return s
-	}
-	syms.Lookup = l.SymLookup
-	syms.ROLookup = func(name string, ver int) *sym.Symbol {
-		i := l.Lookup(name, ver)
-		return l.Syms[i]
-	}
-}
-
-// allocSym allocates a new symbol backing.
-func (l *Loader) allocSym(name string, version int) *sym.Symbol {
-	batch := l.symBatch
-	if len(batch) == 0 {
-		batch = make([]sym.Symbol, 1000)
-	}
-	s := &batch[0]
-	l.symBatch = batch[1:]
-
-	s.Dynid = -1
-	s.Name = name
-	s.Version = int16(version)
-
-	return s
-}
-
-// installSym sets the underlying sym.Symbol for the specified sym index.
-func (l *Loader) installSym(i Sym, s *sym.Symbol) {
-	if s == nil {
-		panic("installSym nil symbol")
-	}
-	if l.Syms[i] != nil {
-		panic("sym already present in installSym")
-	}
-	l.Syms[i] = s
-	s.SymIdx = sym.LoaderSym(i)
-}
-
-// addNewSym adds a new sym.Symbol to the i-th index in the list of symbols.
-func (l *Loader) addNewSym(i Sym, name string, ver int, unit *sym.CompilationUnit, t sym.SymKind) *sym.Symbol {
-	s := l.allocSym(name, ver)
-	if s.Type != 0 && s.Type != sym.SXREF {
-		fmt.Println("symbol already processed:", unit.Lib, i, s)
-		panic("symbol already processed")
-	}
-	if t == sym.SBSS && (s.Type == sym.SRODATA || s.Type == sym.SNOPTRBSS) {
-		t = s.Type
-	}
-	s.Type = t
-	l.growSyms(int(i))
-	l.installSym(i, s)
-	return s
-}
-
 // TopLevelSym tests a symbol (by name and kind) to determine whether
 // the symbol first class sym (participating in the link) or is an
 // anonymous aux or sub-symbol containing some sub-part or payload of
@@ -2483,56 +2105,13 @@
 		return true
 	}
 	switch skind {
-	case sym.SDWARFINFO, sym.SDWARFRANGE, sym.SDWARFLOC, sym.SDWARFLINES, sym.SGOFUNC:
+	case sym.SDWARFFCN, sym.SDWARFABSFCN, sym.SDWARFTYPE, sym.SDWARFCONST, sym.SDWARFCUINFO, sym.SDWARFRANGE, sym.SDWARFLOC, sym.SDWARFLINES, sym.SGOFUNC:
 		return true
 	default:
 		return false
 	}
 }
 
-// loadObjSyms creates sym.Symbol objects for the live Syms in the
-// object corresponding to object reader "r". Return value is the
-// number of sym.Reloc entries required for all the new symbols.
-func loadObjSyms(l *Loader, syms *sym.Symbols, r *oReader, needReloc, needExtReloc bool) int {
-	nr := 0
-	for i, n := 0, r.NSym()+r.NNonpkgdef(); i < n; i++ {
-		gi := r.syms[i]
-		if r2, i2 := l.toLocal(gi); r2 != r || i2 != i {
-			continue // come from a different object
-		}
-		osym := r.Sym(i)
-		name := strings.Replace(osym.Name(r.Reader), "\"\".", r.pkgprefix, -1)
-		t := sym.AbiSymKindToSymKind[objabi.SymKind(osym.Type())]
-
-		// Skip non-dwarf anonymous symbols (e.g. funcdata),
-		// since they will never be turned into sym.Symbols.
-		if !topLevelSym(name, t) {
-			continue
-		}
-		ver := abiToVer(osym.ABI(), r.version)
-		if t == sym.SXREF {
-			log.Fatalf("bad sxref")
-		}
-		if t == 0 {
-			log.Fatalf("missing type for %s in %s", name, r.unit.Lib)
-		}
-		if !l.attrReachable.Has(gi) && name != "runtime.addmoduledata" && name != "runtime.lastmoduledatap" {
-			// No need to load unreachable symbols.
-			// XXX reference to runtime.addmoduledata may be generated later by the linker in plugin mode.
-			continue
-		}
-
-		l.addNewSym(gi, name, ver, r.unit, t)
-		if needReloc {
-			nr += r.NReloc(i)
-		}
-		if needExtReloc && int(gi) < len(l.extRelocs) {
-			nr += len(l.extRelocs[gi])
-		}
-	}
-	return nr
-}
-
 // cloneToExternal takes the existing object file symbol (symIdx)
 // and creates a new external symbol payload that is a clone with
 // respect to name, version, type, relocations, etc. The idea here
@@ -2540,17 +2119,18 @@
 // a symbol originally discovered as part of an object file, it's
 // easier to do this if we make the updates to an external symbol
 // payload.
-// XXX maybe rename? makeExtPayload?
 func (l *Loader) cloneToExternal(symIdx Sym) {
 	if l.IsExternal(symIdx) {
 		panic("sym is already external, no need for clone")
 	}
-	l.growSyms(int(symIdx))
 
 	// Read the particulars from object.
 	r, li := l.toLocal(symIdx)
 	osym := r.Sym(li)
-	sname := strings.Replace(osym.Name(r.Reader), "\"\".", r.pkgprefix, -1)
+	sname := osym.Name(r.Reader)
+	if r.NeedNameExpansion() {
+		sname = strings.Replace(sname, "\"\".", r.pkgprefix, -1)
+	}
 	sver := abiToVer(osym.ABI(), r.version)
 	skind := sym.AbiSymKindToSymKind[objabi.SymKind(osym.Type())]
 
@@ -2564,7 +2144,7 @@
 
 	// If this is a def, then copy the guts. We expect this case
 	// to be very rare (one case it may come up is with -X).
-	if li < (r.NSym() + r.NNonpkgdef()) {
+	if li < uint32(r.NSym()+r.NNonpkgdef()) {
 
 		// Copy relocations
 		relocs := l.Relocs(symIdx)
@@ -2586,22 +2166,11 @@
 	// Gotype, so as to propagate it to the new symbol.
 	auxs := r.Auxs(li)
 	pp.auxs = auxs
-loop:
-	for j := range auxs {
-		a := &auxs[j]
-		switch a.Type() {
-		case goobj2.AuxGotype:
-			pp.gotype = l.resolve(r, a.Sym())
-			break loop
-		default:
-			// nothing to do
-		}
-	}
 
 	// Install new payload to global index space.
 	// (This needs to happen at the end, as the accessors above
 	// need to access the old symbol content.)
-	l.objSyms[symIdx] = objSym{l.extReader, pi}
+	l.objSyms[symIdx] = objSym{l.extReader.objidx, uint32(pi)}
 	l.extReader.syms = append(l.extReader.syms, symIdx)
 }
 
@@ -2649,67 +2218,6 @@
 	l.SetAttrReadOnly(dst, l.AttrReadOnly(src))
 }
 
-// migrateAttributes copies over all of the attributes of symbol 'src' to
-// sym.Symbol 'dst'.
-func (l *Loader) migrateAttributes(src Sym, dst *sym.Symbol) {
-	dst.Value = l.SymValue(src)
-	dst.Align = l.SymAlign(src)
-	dst.Sect = l.SymSect(src)
-
-	dst.Attr.Set(sym.AttrReachable, l.AttrReachable(src))
-	dst.Attr.Set(sym.AttrOnList, l.AttrOnList(src))
-	dst.Attr.Set(sym.AttrLocal, l.AttrLocal(src))
-	dst.Attr.Set(sym.AttrNotInSymbolTable, l.AttrNotInSymbolTable(src))
-	dst.Attr.Set(sym.AttrNoSplit, l.IsNoSplit(src))
-	dst.Attr.Set(sym.AttrVisibilityHidden, l.AttrVisibilityHidden(src))
-	dst.Attr.Set(sym.AttrDuplicateOK, l.AttrDuplicateOK(src))
-	dst.Attr.Set(sym.AttrShared, l.AttrShared(src))
-	dst.Attr.Set(sym.AttrExternal, l.AttrExternal(src))
-	dst.Attr.Set(sym.AttrTopFrame, l.AttrTopFrame(src))
-	dst.Attr.Set(sym.AttrSpecial, l.AttrSpecial(src))
-	dst.Attr.Set(sym.AttrCgoExportDynamic, l.AttrCgoExportDynamic(src))
-	dst.Attr.Set(sym.AttrCgoExportStatic, l.AttrCgoExportStatic(src))
-	dst.Attr.Set(sym.AttrReadOnly, l.AttrReadOnly(src))
-
-	// Convert outer relationship
-	if outer, ok := l.outer[src]; ok {
-		dst.Outer = l.Syms[outer]
-	}
-
-	// Set sub-symbol attribute. See the comment on the AttrSubSymbol
-	// method for more on this, there is some tricky stuff here.
-	dst.Attr.Set(sym.AttrSubSymbol, l.outer[src] != 0 && l.sub[l.outer[src]] != 0)
-
-	// Copy over dynimplib, dynimpvers, extname.
-	if name, ok := l.extname[src]; ok {
-		dst.SetExtname(name)
-	}
-	if l.SymDynimplib(src) != "" {
-		dst.SetDynimplib(l.SymDynimplib(src))
-	}
-	if l.SymDynimpvers(src) != "" {
-		dst.SetDynimpvers(l.SymDynimpvers(src))
-	}
-
-	// Copy ELF type if set.
-	if et, ok := l.elfType[src]; ok {
-		dst.SetElfType(et)
-	}
-
-	// Copy pe objects values if set.
-	if plt, ok := l.plt[src]; ok {
-		dst.SetPlt(plt)
-	}
-	if got, ok := l.got[src]; ok {
-		dst.SetGot(got)
-	}
-
-	// Copy dynid
-	if dynid, ok := l.dynid[src]; ok {
-		dst.Dynid = dynid
-	}
-}
-
 // CreateExtSym creates a new external symbol with the specified name
 // without adding it to any lookup tables, returning a Sym index for it.
 func (l *Loader) CreateExtSym(name string, ver int) Sym {
@@ -2720,8 +2228,7 @@
 // without adding it to any lookup tables, returning a Sym index for it.
 func (l *Loader) CreateStaticSym(name string) Sym {
 	// 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.
+	// symbol so that it is not included in the name lookup table.
 	l.anonVersion--
 	return l.newExtSym(name, l.anonVersion)
 }
@@ -2733,144 +2240,6 @@
 	}
 }
 
-func loadObjFull(l *Loader, r *oReader, needReloc, needExtReloc bool) {
-	for i, n := 0, r.NSym()+r.NNonpkgdef(); i < n; i++ {
-		// A symbol may be a dup or overwritten. In this case, its
-		// content will actually be provided by a different object
-		// (to which its global index points). Skip those symbols.
-		gi := l.toGlobal(r, i)
-		if r2, i2 := l.toLocal(gi); r2 != r || i2 != i {
-			continue
-		}
-		s := l.Syms[gi]
-		if s == nil {
-			continue
-		}
-
-		l.migrateAttributes(gi, s)
-		// Be careful not to overwrite attributes set by the linker.
-		// Don't use the attributes from the object file.
-
-		osym := r.Sym(i)
-		size := osym.Siz()
-
-		// Symbol data
-		s.P = l.OutData(gi)
-
-		// Relocs
-		if needReloc {
-			relocs := l.relocs(r, i)
-			batch := l.relocBatch
-			s.R = batch[:relocs.Count():relocs.Count()]
-			l.relocBatch = batch[relocs.Count():]
-			l.convertRelocations(gi, &relocs, s, false)
-		}
-		if needExtReloc {
-			l.convertExtRelocs(s, gi)
-		}
-
-		// Aux symbol info
-		auxs := r.Auxs(i)
-		for j := range auxs {
-			a := &auxs[j]
-			switch a.Type() {
-			case goobj2.AuxFuncInfo, goobj2.AuxFuncdata, goobj2.AuxGotype:
-				// already handled
-			case goobj2.AuxDwarfInfo, goobj2.AuxDwarfLoc, goobj2.AuxDwarfRanges, goobj2.AuxDwarfLines:
-				// ignored for now
-			default:
-				panic("unknown aux type")
-			}
-		}
-
-		if s.Size < int64(size) {
-			s.Size = int64(size)
-		}
-	}
-}
-
-// convertRelocations takes a vector of loader.Reloc relocations and
-// translates them into an equivalent set of sym.Reloc relocations on
-// the symbol "dst", performing fixups along the way for ABI aliases,
-// etc. It is assumed that the caller has pre-allocated the dst symbol
-// relocations slice. If 'strict' is set, then this method will
-// panic if it finds a relocation targeting a nil symbol.
-func (l *Loader) convertRelocations(symIdx Sym, src *Relocs, dst *sym.Symbol, strict bool) {
-	for j := range dst.R {
-		r := src.At2(j)
-		rs := r.Sym()
-		sz := r.Siz()
-		rt := r.Type()
-		if rt == objabi.R_METHODOFF {
-			if l.attrReachable.Has(rs) {
-				rt = objabi.R_ADDROFF
-			} else {
-				sz = 0
-				rs = 0
-			}
-		}
-		if rt == objabi.R_WEAKADDROFF && !l.attrReachable.Has(rs) {
-			rs = 0
-			sz = 0
-		}
-		if rs != 0 && l.Syms[rs] != nil && l.Syms[rs].Type == sym.SABIALIAS {
-			rsrelocs := l.Relocs(rs)
-			rs = rsrelocs.At2(0).Sym()
-		}
-		if strict && rs != 0 && l.Syms[rs] == nil && rt != objabi.R_USETYPE {
-			panic("nil reloc target in convertRelocations")
-		}
-		dst.R[j] = sym.Reloc{
-			Off:  r.Off(),
-			Siz:  sz,
-			Type: rt,
-			Add:  r.Add(),
-			Sym:  l.Syms[rs],
-		}
-		if rv := l.RelocVariant(symIdx, j); rv != 0 {
-			dst.R[j].InitExt()
-			dst.R[j].Variant = rv
-		}
-	}
-}
-
-// Convert external relocations to sym.Relocs on symbol dst.
-func (l *Loader) convertExtRelocs(dst *sym.Symbol, src Sym) {
-	if int(src) >= len(l.extRelocs) {
-		return
-	}
-	extRelocs := l.extRelocs[src]
-	if len(extRelocs) == 0 {
-		return
-	}
-	if len(dst.R) != 0 {
-		panic("bad")
-	}
-
-	n := len(extRelocs)
-	batch := l.relocBatch
-	dst.R = batch[:n:n]
-	l.relocBatch = batch[n:]
-	relocs := l.Relocs(src)
-	for i := range dst.R {
-		er := &extRelocs[i]
-		sr := relocs.At2(er.Idx)
-		r := &dst.R[i]
-		r.RelocExt = &l.relocExtBatch[0]
-		l.relocExtBatch = l.relocExtBatch[1:]
-		r.Off = sr.Off()
-		r.Siz = sr.Siz()
-		r.Type = sr.Type()
-		r.Sym = l.Syms[l.ResolveABIAlias(sr.Sym())]
-		r.Add = sr.Add()
-		r.Xsym = l.Syms[er.Xsym]
-		r.Xadd = er.Xadd
-		if rv := l.RelocVariant(src, er.Idx); rv != 0 {
-			r.Variant = rv
-		}
-	}
-}
-
 // relocId is essentially a <S,R> tuple identifying the Rth
 // relocation of symbol S.
 type relocId struct {
@@ -2927,19 +2296,19 @@
 	return result
 }
 
-// AssignTextSymbolOrder populates the Textp2 slices within each
+// AssignTextSymbolOrder populates the Textp slices within each
 // library and compilation unit, insuring that packages are laid down
 // in dependency order (internal first, then everything else). Return value
 // is a slice of all text syms.
 func (l *Loader) AssignTextSymbolOrder(libs []*sym.Library, intlibs []bool, extsyms []Sym) []Sym {
 
-	// Library Textp2 lists should be empty at this point.
+	// Library Textp lists should be empty at this point.
 	for _, lib := range libs {
-		if len(lib.Textp2) != 0 {
-			panic("expected empty Textp2 slice for library")
+		if len(lib.Textp) != 0 {
+			panic("expected empty Textp slice for library")
 		}
-		if len(lib.DupTextSyms2) != 0 {
-			panic("expected empty DupTextSyms2 slice for library")
+		if len(lib.DupTextSyms) != 0 {
+			panic("expected empty DupTextSyms slice for library")
 		}
 	}
 
@@ -2950,21 +2319,21 @@
 	// call the regular addToTextp.
 	assignedToUnit := MakeBitmap(l.NSym() + 1)
 
-	// Start off textp2 with reachable external syms.
-	textp2 := []Sym{}
+	// Start off textp with reachable external syms.
+	textp := []Sym{}
 	for _, sym := range extsyms {
 		if !l.attrReachable.Has(sym) {
 			continue
 		}
-		textp2 = append(textp2, sym)
+		textp = append(textp, sym)
 	}
 
 	// Walk through all text symbols from Go object files and append
-	// them to their corresponding library's textp2 list.
-	for _, o := range l.objs[1:] {
+	// them to their corresponding library's textp list.
+	for _, o := range l.objs[goObjStart:] {
 		r := o.r
 		lib := r.unit.Lib
-		for i, n := 0, r.NSym()+r.NNonpkgdef(); i < n; i++ {
+		for i, n := uint32(0), uint32(r.NSym()+r.NNonpkgdef()); i < n; i++ {
 			gi := l.toGlobal(r, i)
 			if !l.attrReachable.Has(gi) {
 				continue
@@ -2980,15 +2349,15 @@
 				// We still need to record its presence in the current
 				// package, as the trampoline pass expects packages
 				// are laid out in dependency order.
-				lib.DupTextSyms2 = append(lib.DupTextSyms2, sym.LoaderSym(gi))
+				lib.DupTextSyms = append(lib.DupTextSyms, sym.LoaderSym(gi))
 				continue // symbol in different object
 			}
 			if dupok {
-				lib.DupTextSyms2 = append(lib.DupTextSyms2, sym.LoaderSym(gi))
+				lib.DupTextSyms = append(lib.DupTextSyms, sym.LoaderSym(gi))
 				continue
 			}
 
-			lib.Textp2 = append(lib.Textp2, sym.LoaderSym(gi))
+			lib.Textp = append(lib.Textp, sym.LoaderSym(gi))
 		}
 	}
 
@@ -2998,15 +2367,15 @@
 			if intlibs[idx] != doInternal {
 				continue
 			}
-			lists := [2][]sym.LoaderSym{lib.Textp2, lib.DupTextSyms2}
+			lists := [2][]sym.LoaderSym{lib.Textp, lib.DupTextSyms}
 			for i, list := range lists {
 				for _, s := range list {
 					sym := Sym(s)
 					if l.attrReachable.Has(sym) && !assignedToUnit.Has(sym) {
-						textp2 = append(textp2, sym)
+						textp = append(textp, sym)
 						unit := l.SymUnit(sym)
 						if unit != nil {
-							unit.Textp2 = append(unit.Textp2, s)
+							unit.Textp = append(unit.Textp, s)
 							assignedToUnit.Set(sym)
 						}
 						// Dupok symbols may be defined in multiple packages; the
@@ -3020,12 +2389,12 @@
 					}
 				}
 			}
-			lib.Textp2 = nil
-			lib.DupTextSyms2 = nil
+			lib.Textp = nil
+			lib.DupTextSyms = nil
 		}
 	}
 
-	return textp2
+	return textp
 }
 
 // ErrorReporter is a helper class for reporting errors.
@@ -3067,7 +2436,7 @@
 // For debugging.
 func (l *Loader) Dump() {
 	fmt.Println("objs")
-	for _, obj := range l.objs {
+	for _, obj := range l.objs[goObjStart:] {
 		if obj.r != nil {
 			fmt.Println(obj.i, obj.r.unit.Lib)
 		}
@@ -3080,15 +2449,7 @@
 		if l.IsExternal(i) {
 			pi = fmt.Sprintf("<ext %d>", l.extIndex(i))
 		}
-		var s *sym.Symbol
-		if int(i) < len(l.Syms) {
-			s = l.Syms[i]
-		}
-		if s != nil {
-			fmt.Println(i, s, s.Type, pi)
-		} else {
-			fmt.Println(i, l.SymName(i), "<not loaded>", pi)
-		}
+		fmt.Println(i, l.SymName(i), l.SymType(i), pi)
 	}
 	fmt.Println("symsByName")
 	for name, i := range l.symsByName[0] {
diff --git a/src/cmd/link/internal/loader/loader_test.go b/src/cmd/link/internal/loader/loader_test.go
index 60ef69a..8805a1e 100644
--- a/src/cmd/link/internal/loader/loader_test.go
+++ b/src/cmd/link/internal/loader/loader_test.go
@@ -19,7 +19,7 @@
 // do anything interesting with this symbol (such as look at its
 // data or relocations).
 func addDummyObjSym(t *testing.T, ldr *Loader, or *oReader, name string) Sym {
-	idx := len(ldr.objSyms)
+	idx := uint32(len(ldr.objSyms))
 	s, ok := ldr.AddSym(name, 0, or, idx, nonPkgDef, false, sym.SRODATA)
 	if !ok {
 		t.Errorf("AddrSym failed for '" + name + "'")
@@ -28,7 +28,7 @@
 }
 
 func mkLoader() *Loader {
-	edummy := func(s *sym.Symbol, str string, off int) {}
+	edummy := func(str string, off int) {}
 	er := ErrorReporter{}
 	ldr := NewLoader(0, edummy, &er)
 	er.ldr = ldr
@@ -72,7 +72,9 @@
 	// Suppose we create some more symbols, which triggers a grow.
 	// Make sure the symbol builder's payload pointer is valid,
 	// even across a grow.
-	ldr.growSyms(9999)
+	for i := 0; i < 9999; i++ {
+		ldr.CreateStaticSym("dummy")
+	}
 
 	// Check get/set symbol type
 	es3typ := sb3.Type()
diff --git a/src/cmd/link/internal/loader/symbolbuilder.go b/src/cmd/link/internal/loader/symbolbuilder.go
index 70adb36..b6e07db 100644
--- a/src/cmd/link/internal/loader/symbolbuilder.go
+++ b/src/cmd/link/internal/loader/symbolbuilder.go
@@ -9,7 +9,6 @@
 	"cmd/internal/objabi"
 	"cmd/internal/sys"
 	"cmd/link/internal/sym"
-	"fmt"
 	"sort"
 )
 
@@ -26,9 +25,6 @@
 func (l *Loader) MakeSymbolBuilder(name string) *SymbolBuilder {
 	// for now assume that any new sym is intended to be static
 	symIdx := l.CreateStaticSym(name)
-	if l.Syms[symIdx] != nil {
-		panic("can't build if sym.Symbol already present")
-	}
 	sb := &SymbolBuilder{l: l, symIdx: symIdx}
 	sb.extSymPayload = l.getPayload(symIdx)
 	return sb
@@ -47,14 +43,6 @@
 		// Create a clone with the same name/version/kind etc.
 		l.cloneToExternal(symIdx)
 	}
-	// Now that we're doing phase 2 DWARF generation using the loader
-	// but before the wavefront has reached dodata(), we can't have this
-	// assertion here. Commented out for now.
-	if false {
-		if l.Syms[symIdx] != nil {
-			panic(fmt.Sprintf("can't build if sym.Symbol %q already present", l.RawSymName(symIdx)))
-		}
-	}
 
 	// Construct updater and return.
 	sb := &SymbolBuilder{l: l, symIdx: symIdx}
@@ -363,7 +351,7 @@
 	r := sb.size
 	if sb.name == ".shstrtab" {
 		// FIXME: find a better mechanism for this
-		sb.l.elfsetstring(nil, str, int(r))
+		sb.l.elfsetstring(str, int(r))
 	}
 	sb.data = append(sb.data, str...)
 	sb.data = append(sb.data, 0)
diff --git a/src/cmd/link/internal/mips/asm.go b/src/cmd/link/internal/mips/asm.go
index 9710b9c..d0e0245 100644
--- a/src/cmd/link/internal/mips/asm.go
+++ b/src/cmd/link/internal/mips/asm.go
@@ -37,29 +37,21 @@
 	"cmd/link/internal/loader"
 	"cmd/link/internal/sym"
 	"debug/elf"
-	"fmt"
-	"log"
-	"sync"
 )
 
-func gentext2(ctxt *ld.Link, ldr *loader.Loader) {
+func gentext(ctxt *ld.Link, ldr *loader.Loader) {
 	return
 }
 
-func adddynrel(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s *sym.Symbol, r *sym.Reloc) bool {
-	log.Fatalf("adddynrel not implemented")
-	return false
-}
-
-func elfreloc1(ctxt *ld.Link, r *sym.Reloc, sectoff int64) bool {
+func elfreloc1(ctxt *ld.Link, ldr *loader.Loader, s loader.Sym, r loader.ExtRelocView, sectoff int64) bool {
 	ctxt.Out.Write32(uint32(sectoff))
 
 	elfsym := ld.ElfSymForReloc(ctxt, r.Xsym)
-	switch r.Type {
+	switch r.Type() {
 	default:
 		return false
 	case objabi.R_ADDR, objabi.R_DWARFSECREF:
-		if r.Siz != 4 {
+		if r.Siz() != 4 {
 			return false
 		}
 		ctxt.Out.Write32(uint32(elf.R_MIPS_32) | uint32(elfsym)<<8)
@@ -80,13 +72,13 @@
 	return
 }
 
-func machoreloc1(arch *sys.Arch, out *ld.OutBuf, s *sym.Symbol, r *sym.Reloc, sectoff int64) bool {
+func machoreloc1(*sys.Arch, *ld.OutBuf, *loader.Loader, loader.Sym, loader.ExtRelocView, int64) bool {
 	return false
 }
 
-func applyrel(arch *sys.Arch, r *sym.Reloc, s *sym.Symbol, val int64, t int64) int64 {
-	o := arch.ByteOrder.Uint32(s.P[r.Off:])
-	switch r.Type {
+func applyrel(arch *sys.Arch, ldr *loader.Loader, rt objabi.RelocType, off int32, s loader.Sym, val int64, t int64) int64 {
+	o := arch.ByteOrder.Uint32(ldr.OutData(s)[off:])
+	switch rt {
 	case objabi.R_ADDRMIPS, objabi.R_ADDRMIPSTLS:
 		return int64(o&0xffff0000 | uint32(t)&0xffff)
 	case objabi.R_ADDRMIPSU:
@@ -98,133 +90,63 @@
 	}
 }
 
-func archreloc(target *ld.Target, syms *ld.ArchSyms, r *sym.Reloc, s *sym.Symbol, val int64) (int64, bool) {
+func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loader.Reloc2, rr *loader.ExtReloc, s loader.Sym, val int64) (o int64, needExtReloc bool, ok bool) {
+	rs := r.Sym()
+	rs = ldr.ResolveABIAlias(rs)
 	if target.IsExternal() {
-		switch r.Type {
+		switch r.Type() {
 		default:
-			return val, false
+			return val, false, false
+
 		case objabi.R_ADDRMIPS, objabi.R_ADDRMIPSU:
-			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 += ld.Symaddr(rs) - ld.Symaddr(rs.Outer)
-				rs = rs.Outer
+			rs, off := ld.FoldSubSymbolOffset(ldr, rs)
+			rr.Xadd = r.Add() + off
+			rst := ldr.SymType(rs)
+			if rst != sym.SHOSTOBJ && rst != sym.SDYNIMPORT && ldr.SymSect(rs) == nil {
+				ldr.Errorf(s, "missing section for %s", ldr.SymName(rs))
 			}
+			rr.Xsym = rs
+			return applyrel(target.Arch, ldr, r.Type(), r.Off(), s, val, rr.Xadd), true, true
 
-			if rs.Type != sym.SHOSTOBJ && rs.Type != sym.SDYNIMPORT && rs.Sect == nil {
-				ld.Errorf(s, "missing section for %s", rs.Name)
-			}
-			r.Xsym = rs
-			return applyrel(target.Arch, r, s, val, r.Xadd), true
 		case objabi.R_ADDRMIPSTLS, objabi.R_CALLMIPS, objabi.R_JMPMIPS:
-			r.Done = false
-			r.Xsym = r.Sym
-			r.Xadd = r.Add
-			return applyrel(target.Arch, r, s, val, r.Add), true
+			rr.Xsym = rs
+			rr.Xadd = r.Add()
+			return applyrel(target.Arch, ldr, r.Type(), r.Off(), s, val, rr.Xadd), true, true
 		}
 	}
 
-	switch r.Type {
-	case objabi.R_CONST:
-		return r.Add, true
-	case objabi.R_GOTOFF:
-		return ld.Symaddr(r.Sym) + r.Add - ld.Symaddr(syms.GOT), true
+	const isOk = true
+	const noExtReloc = false
+	switch rt := r.Type(); rt {
 	case objabi.R_ADDRMIPS, objabi.R_ADDRMIPSU:
-		t := ld.Symaddr(r.Sym) + r.Add
-		return applyrel(target.Arch, r, s, val, t), true
+		t := ldr.SymValue(rs) + r.Add()
+		return applyrel(target.Arch, ldr, rt, r.Off(), s, val, t), noExtReloc, isOk
 	case objabi.R_CALLMIPS, objabi.R_JMPMIPS:
-		t := ld.Symaddr(r.Sym) + r.Add
+		t := ldr.SymValue(rs) + r.Add()
 
 		if t&3 != 0 {
-			ld.Errorf(s, "direct call is not aligned: %s %x", r.Sym.Name, t)
+			ldr.Errorf(s, "direct call is not aligned: %s %x", ldr.SymName(rs), t)
 		}
 
 		// check if target address is in the same 256 MB region as the next instruction
-		if (s.Value+int64(r.Off)+4)&0xf0000000 != (t & 0xf0000000) {
-			ld.Errorf(s, "direct call too far: %s %x", r.Sym.Name, t)
+		if (ldr.SymValue(s)+int64(r.Off())+4)&0xf0000000 != (t & 0xf0000000) {
+			ldr.Errorf(s, "direct call too far: %s %x", ldr.SymName(rs), t)
 		}
 
-		return applyrel(target.Arch, r, s, val, t), true
+		return applyrel(target.Arch, ldr, rt, r.Off(), s, val, t), noExtReloc, isOk
 	case objabi.R_ADDRMIPSTLS:
 		// thread pointer is at 0x7000 offset from the start of TLS data area
-		t := ld.Symaddr(r.Sym) + r.Add - 0x7000
+		t := ldr.SymValue(rs) + r.Add() - 0x7000
 		if t < -32768 || t >= 32678 {
-			ld.Errorf(s, "TLS offset out of range %d", t)
+			ldr.Errorf(s, "TLS offset out of range %d", t)
 		}
-		return applyrel(target.Arch, r, s, val, t), true
+		return applyrel(target.Arch, ldr, rt, r.Off(), s, val, t), noExtReloc, isOk
 	}
 
-	return val, false
+	return val, false, false
 }
 
-func archrelocvariant(target *ld.Target, syms *ld.ArchSyms, r *sym.Reloc, s *sym.Symbol, t int64) int64 {
+func archrelocvariant(*ld.Target, *loader.Loader, loader.Reloc2, sym.RelocVariant, loader.Sym, int64) int64 {
 	return -1
 }
-
-func asmb(ctxt *ld.Link, _ *loader.Loader) {
-	if ctxt.IsELF {
-		ld.Asmbelfsetup()
-	}
-
-	var wg sync.WaitGroup
-	sect := ld.Segtext.Sections[0]
-	offset := sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff
-	ld.WriteParallel(&wg, ld.Codeblk, ctxt, offset, sect.Vaddr, sect.Length)
-
-	for _, sect = range ld.Segtext.Sections[1:] {
-		offset := sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff
-		ld.WriteParallel(&wg, ld.Datblk, ctxt, offset, sect.Vaddr, sect.Length)
-	}
-
-	if ld.Segrodata.Filelen > 0 {
-		ld.WriteParallel(&wg, ld.Datblk, ctxt, ld.Segrodata.Fileoff, ld.Segrodata.Vaddr, ld.Segrodata.Filelen)
-	}
-
-	ld.WriteParallel(&wg, ld.Datblk, ctxt, ld.Segdata.Fileoff, ld.Segdata.Vaddr, ld.Segdata.Filelen)
-
-	ld.WriteParallel(&wg, ld.Dwarfblk, ctxt, ld.Segdwarf.Fileoff, ld.Segdwarf.Vaddr, ld.Segdwarf.Filelen)
-	wg.Wait()
-}
-
-func asmb2(ctxt *ld.Link) {
-	/* output symbol table */
-	ld.Symsize = 0
-
-	ld.Lcsize = 0
-	symo := uint32(0)
-	if !*ld.FlagS {
-		if !ctxt.IsELF {
-			ld.Errorf(nil, "unsupported executable format")
-		}
-		symo = uint32(ld.Segdwarf.Fileoff + ld.Segdwarf.Filelen)
-		symo = uint32(ld.Rnd(int64(symo), int64(*ld.FlagRound)))
-
-		ctxt.Out.SeekSet(int64(symo))
-		ld.Asmelfsym(ctxt)
-		ctxt.Out.Write(ld.Elfstrdat)
-
-		if ctxt.LinkMode == ld.LinkExternal {
-			ld.Elfemitreloc(ctxt)
-		}
-	}
-
-	ctxt.Out.SeekSet(0)
-	switch ctxt.HeadType {
-	default:
-		ld.Errorf(nil, "unsupported operating system")
-	case objabi.Hlinux:
-		ld.Asmbelf(ctxt, int64(symo))
-	}
-
-	if *ld.FlagC {
-		fmt.Printf("textsize=%d\n", ld.Segtext.Filelen)
-		fmt.Printf("datsize=%d\n", ld.Segdata.Filelen)
-		fmt.Printf("bsssize=%d\n", ld.Segdata.Length-ld.Segdata.Filelen)
-		fmt.Printf("symsize=%d\n", ld.Symsize)
-		fmt.Printf("lcsize=%d\n", ld.Lcsize)
-		fmt.Printf("total=%d\n", ld.Segtext.Filelen+ld.Segdata.Length+uint64(ld.Symsize)+uint64(ld.Lcsize))
-	}
-}
diff --git a/src/cmd/link/internal/mips/obj.go b/src/cmd/link/internal/mips/obj.go
index f95c776..cc3cc43 100644
--- a/src/cmd/link/internal/mips/obj.go
+++ b/src/cmd/link/internal/mips/obj.go
@@ -49,15 +49,12 @@
 		Dwarfregsp: DWARFREGSP,
 		Dwarfreglr: DWARFREGLR,
 
-		Adddynrel:        adddynrel,
 		Archinit:         archinit,
 		Archreloc:        archreloc,
 		Archrelocvariant: archrelocvariant,
-		Asmb:             asmb,
-		Asmb2:            asmb2,
 		Elfreloc1:        elfreloc1,
 		Elfsetupplt:      elfsetupplt,
-		Gentext2:         gentext2,
+		Gentext:          gentext,
 		Machoreloc1:      machoreloc1,
 
 		Linuxdynld: "/lib/ld.so.1",
diff --git a/src/cmd/link/internal/mips64/asm.go b/src/cmd/link/internal/mips64/asm.go
index b48241b..dcca72c 100644
--- a/src/cmd/link/internal/mips64/asm.go
+++ b/src/cmd/link/internal/mips64/asm.go
@@ -37,19 +37,12 @@
 	"cmd/link/internal/loader"
 	"cmd/link/internal/sym"
 	"debug/elf"
-	"fmt"
-	"log"
-	"sync"
 )
 
-func gentext2(ctxt *ld.Link, ldr *loader.Loader) {}
+func gentext(ctxt *ld.Link, ldr *loader.Loader) {}
 
-func adddynrel(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s *sym.Symbol, r *sym.Reloc) bool {
-	log.Fatalf("adddynrel not implemented")
-	return false
-}
+func elfreloc1(ctxt *ld.Link, ldr *loader.Loader, s loader.Sym, r loader.ExtRelocView, sectoff int64) bool {
 
-func elfreloc1(ctxt *ld.Link, r *sym.Reloc, sectoff int64) bool {
 	// mips64 ELF relocation (endian neutral)
 	//		offset	uint64
 	//		sym		uint32
@@ -66,11 +59,11 @@
 	ctxt.Out.Write8(0)
 	ctxt.Out.Write8(0)
 	ctxt.Out.Write8(0)
-	switch r.Type {
+	switch r.Type() {
 	default:
 		return false
 	case objabi.R_ADDR, objabi.R_DWARFSECREF:
-		switch r.Siz {
+		switch r.Siz() {
 		case 4:
 			ctxt.Out.Write8(uint8(elf.R_MIPS_32))
 		case 8:
@@ -97,180 +90,69 @@
 	return
 }
 
-func machoreloc1(arch *sys.Arch, out *ld.OutBuf, s *sym.Symbol, r *sym.Reloc, sectoff int64) bool {
+func machoreloc1(*sys.Arch, *ld.OutBuf, *loader.Loader, loader.Sym, loader.ExtRelocView, int64) bool {
 	return false
 }
 
-func archreloc(target *ld.Target, syms *ld.ArchSyms, r *sym.Reloc, s *sym.Symbol, val int64) (int64, bool) {
+func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loader.Reloc2, rr *loader.ExtReloc, s loader.Sym, val int64) (o int64, needExtReloc bool, ok bool) {
+	rs := r.Sym()
+	rs = ldr.ResolveABIAlias(rs)
 	if target.IsExternal() {
-		switch r.Type {
+		switch r.Type() {
 		default:
-			return val, false
+			return val, false, false
+
 		case objabi.R_ADDRMIPS,
 			objabi.R_ADDRMIPSU:
-			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 += ld.Symaddr(rs) - ld.Symaddr(rs.Outer)
-				rs = rs.Outer
+			rs, off := ld.FoldSubSymbolOffset(ldr, rs)
+			rr.Xadd = r.Add() + off
+			rst := ldr.SymType(rs)
+			if rst != sym.SHOSTOBJ && rst != sym.SDYNIMPORT && ldr.SymSect(rs) == nil {
+				ldr.Errorf(s, "missing section for %s", ldr.SymName(rs))
 			}
+			rr.Xsym = rs
+			return val, true, true
 
-			if rs.Type != sym.SHOSTOBJ && rs.Type != sym.SDYNIMPORT && rs.Sect == nil {
-				ld.Errorf(s, "missing section for %s", rs.Name)
-			}
-			r.Xsym = rs
-
-			return val, true
 		case objabi.R_ADDRMIPSTLS,
 			objabi.R_CALLMIPS,
 			objabi.R_JMPMIPS:
-			r.Done = false
-			r.Xsym = r.Sym
-			r.Xadd = r.Add
-			return val, true
+			rr.Xsym = rs
+			rr.Xadd = r.Add()
+			return val, true, true
 		}
 	}
 
-	switch r.Type {
-	case objabi.R_CONST:
-		return r.Add, true
-	case objabi.R_GOTOFF:
-		return ld.Symaddr(r.Sym) + r.Add - ld.Symaddr(syms.GOT), true
+	const isOk = true
+	const noExtReloc = false
+	switch r.Type() {
 	case objabi.R_ADDRMIPS,
 		objabi.R_ADDRMIPSU:
-		t := ld.Symaddr(r.Sym) + r.Add
-		o1 := target.Arch.ByteOrder.Uint32(s.P[r.Off:])
-		if r.Type == objabi.R_ADDRMIPS {
-			return int64(o1&0xffff0000 | uint32(t)&0xffff), true
+		t := ldr.SymValue(rs) + r.Add()
+		o1 := target.Arch.ByteOrder.Uint32(ldr.OutData(s)[r.Off():])
+		if r.Type() == objabi.R_ADDRMIPS {
+			return int64(o1&0xffff0000 | uint32(t)&0xffff), noExtReloc, isOk
 		}
-		return int64(o1&0xffff0000 | uint32((t+1<<15)>>16)&0xffff), true
+		return int64(o1&0xffff0000 | uint32((t+1<<15)>>16)&0xffff), noExtReloc, isOk
 	case objabi.R_ADDRMIPSTLS:
 		// thread pointer is at 0x7000 offset from the start of TLS data area
-		t := ld.Symaddr(r.Sym) + r.Add - 0x7000
+		t := ldr.SymValue(rs) + r.Add() - 0x7000
 		if t < -32768 || t >= 32678 {
-			ld.Errorf(s, "TLS offset out of range %d", t)
+			ldr.Errorf(s, "TLS offset out of range %d", t)
 		}
-		o1 := target.Arch.ByteOrder.Uint32(s.P[r.Off:])
-		return int64(o1&0xffff0000 | uint32(t)&0xffff), true
+		o1 := target.Arch.ByteOrder.Uint32(ldr.OutData(s)[r.Off():])
+		return int64(o1&0xffff0000 | uint32(t)&0xffff), noExtReloc, isOk
 	case objabi.R_CALLMIPS,
 		objabi.R_JMPMIPS:
 		// Low 26 bits = (S + A) >> 2
-		t := ld.Symaddr(r.Sym) + r.Add
-		o1 := target.Arch.ByteOrder.Uint32(s.P[r.Off:])
-		return int64(o1&0xfc000000 | uint32(t>>2)&^0xfc000000), true
+		t := ldr.SymValue(rs) + r.Add()
+		o1 := target.Arch.ByteOrder.Uint32(ldr.OutData(s)[r.Off():])
+		return int64(o1&0xfc000000 | uint32(t>>2)&^0xfc000000), noExtReloc, isOk
 	}
 
-	return val, false
+	return val, false, false
 }
 
-func archrelocvariant(target *ld.Target, syms *ld.ArchSyms, r *sym.Reloc, s *sym.Symbol, t int64) int64 {
+func archrelocvariant(*ld.Target, *loader.Loader, loader.Reloc2, sym.RelocVariant, loader.Sym, int64) int64 {
 	return -1
 }
-
-func asmb(ctxt *ld.Link, _ *loader.Loader) {
-	if ctxt.IsELF {
-		ld.Asmbelfsetup()
-	}
-
-	var wg sync.WaitGroup
-	sect := ld.Segtext.Sections[0]
-	offset := sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff
-	ld.WriteParallel(&wg, ld.Codeblk, ctxt, offset, sect.Vaddr, sect.Length)
-
-	for _, sect := range ld.Segtext.Sections[1:] {
-		offset := sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff
-		ld.WriteParallel(&wg, ld.Datblk, ctxt, offset, sect.Vaddr, sect.Length)
-	}
-
-	if ld.Segrodata.Filelen > 0 {
-		ld.WriteParallel(&wg, ld.Datblk, ctxt, ld.Segrodata.Fileoff, ld.Segrodata.Vaddr, ld.Segrodata.Filelen)
-	}
-
-	if ld.Segrelrodata.Filelen > 0 {
-		ld.WriteParallel(&wg, ld.Datblk, ctxt, ld.Segrelrodata.Fileoff, ld.Segrelrodata.Vaddr, ld.Segrelrodata.Filelen)
-	}
-
-	ld.WriteParallel(&wg, ld.Datblk, ctxt, ld.Segdata.Fileoff, ld.Segdata.Vaddr, ld.Segdata.Filelen)
-
-	ld.WriteParallel(&wg, ld.Dwarfblk, ctxt, ld.Segdwarf.Fileoff, ld.Segdwarf.Vaddr, ld.Segdwarf.Filelen)
-	wg.Wait()
-}
-
-func asmb2(ctxt *ld.Link) {
-	/* output symbol table */
-	ld.Symsize = 0
-
-	ld.Lcsize = 0
-	symo := uint32(0)
-	if !*ld.FlagS {
-		// TODO: rationalize
-		switch ctxt.HeadType {
-		default:
-			if ctxt.IsELF {
-				symo = uint32(ld.Segdwarf.Fileoff + ld.Segdwarf.Filelen)
-				symo = uint32(ld.Rnd(int64(symo), int64(*ld.FlagRound)))
-			}
-
-		case objabi.Hplan9:
-			symo = uint32(ld.Segdata.Fileoff + ld.Segdata.Filelen)
-		}
-
-		ctxt.Out.SeekSet(int64(symo))
-		switch ctxt.HeadType {
-		default:
-			if ctxt.IsELF {
-				ld.Asmelfsym(ctxt)
-				ctxt.Out.Write(ld.Elfstrdat)
-
-				if ctxt.LinkMode == ld.LinkExternal {
-					ld.Elfemitreloc(ctxt)
-				}
-			}
-
-		case objabi.Hplan9:
-			ld.Asmplan9sym(ctxt)
-
-			sym := ctxt.Syms.Lookup("pclntab", 0)
-			if sym != nil {
-				ld.Lcsize = int32(len(sym.P))
-				ctxt.Out.Write(sym.P)
-			}
-		}
-	}
-
-	ctxt.Out.SeekSet(0)
-	switch ctxt.HeadType {
-	default:
-	case objabi.Hplan9: /* plan 9 */
-		magic := uint32(4*18*18 + 7)
-		if ctxt.Arch == sys.ArchMIPS64LE {
-			magic = uint32(4*26*26 + 7)
-		}
-		ctxt.Out.Write32(magic)                      /* magic */
-		ctxt.Out.Write32(uint32(ld.Segtext.Filelen)) /* sizes */
-		ctxt.Out.Write32(uint32(ld.Segdata.Filelen))
-		ctxt.Out.Write32(uint32(ld.Segdata.Length - ld.Segdata.Filelen))
-		ctxt.Out.Write32(uint32(ld.Symsize))          /* nsyms */
-		ctxt.Out.Write32(uint32(ld.Entryvalue(ctxt))) /* va of entry */
-		ctxt.Out.Write32(0)
-		ctxt.Out.Write32(uint32(ld.Lcsize))
-
-	case objabi.Hlinux,
-		objabi.Hfreebsd,
-		objabi.Hnetbsd,
-		objabi.Hopenbsd:
-		ld.Asmbelf(ctxt, int64(symo))
-	}
-
-	if *ld.FlagC {
-		fmt.Printf("textsize=%d\n", ld.Segtext.Filelen)
-		fmt.Printf("datsize=%d\n", ld.Segdata.Filelen)
-		fmt.Printf("bsssize=%d\n", ld.Segdata.Length-ld.Segdata.Filelen)
-		fmt.Printf("symsize=%d\n", ld.Symsize)
-		fmt.Printf("lcsize=%d\n", ld.Lcsize)
-		fmt.Printf("total=%d\n", ld.Segtext.Filelen+ld.Segdata.Length+uint64(ld.Symsize)+uint64(ld.Lcsize))
-	}
-}
diff --git a/src/cmd/link/internal/mips64/obj.go b/src/cmd/link/internal/mips64/obj.go
index 5efa356..449a200 100644
--- a/src/cmd/link/internal/mips64/obj.go
+++ b/src/cmd/link/internal/mips64/obj.go
@@ -48,15 +48,12 @@
 		Minalign:         minAlign,
 		Dwarfregsp:       dwarfRegSP,
 		Dwarfreglr:       dwarfRegLR,
-		Adddynrel:        adddynrel,
 		Archinit:         archinit,
 		Archreloc:        archreloc,
 		Archrelocvariant: archrelocvariant,
-		Asmb:             asmb,
-		Asmb2:            asmb2,
 		Elfreloc1:        elfreloc1,
 		Elfsetupplt:      elfsetupplt,
-		Gentext2:         gentext2,
+		Gentext:          gentext,
 		Machoreloc1:      machoreloc1,
 
 		Linuxdynld:     "/lib64/ld64.so.1",
diff --git a/src/cmd/link/internal/ppc64/asm.go b/src/cmd/link/internal/ppc64/asm.go
index b1c0873..ed086f0 100644
--- a/src/cmd/link/internal/ppc64/asm.go
+++ b/src/cmd/link/internal/ppc64/asm.go
@@ -41,10 +41,9 @@
 	"fmt"
 	"log"
 	"strings"
-	"sync"
 )
 
-func genplt2(ctxt *ld.Link, ldr *loader.Loader) {
+func genplt(ctxt *ld.Link, ldr *loader.Loader) {
 	// The ppc64 ABI PLT has similar concepts to other
 	// architectures, but is laid out quite differently. When we
 	// see an R_PPC64_REL24 relocation to a dynamic symbol
@@ -94,7 +93,7 @@
 	// This assumes "case 1" from the ABI, where the caller needs
 	// us to save and restore the TOC pointer.
 	var stubs []loader.Sym
-	for _, s := range ctxt.Textp2 {
+	for _, s := range ctxt.Textp {
 		relocs := ldr.Relocs(s)
 		for i := 0; i < relocs.Count(); i++ {
 			r := relocs.At2(i)
@@ -104,7 +103,7 @@
 
 			// Reserve PLT entry and generate symbol
 			// resolver
-			addpltsym2(ctxt, ldr, r.Sym())
+			addpltsym(ctxt, ldr, r.Sym())
 
 			// Generate call stub. Important to note that we're looking
 			// up the stub using the same version as the parent symbol (s),
@@ -116,7 +115,7 @@
 			stub := ldr.CreateSymForUpdate(n, ldr.SymVersion(s))
 			if stub.Size() == 0 {
 				stubs = append(stubs, stub.Sym())
-				gencallstub2(ctxt, ldr, 1, stub, r.Sym())
+				gencallstub(ctxt, ldr, 1, stub, r.Sym())
 			}
 
 			// Update the relocation to use the call stub
@@ -138,10 +137,10 @@
 	// So when resolving the relocations to calls to the stubs,
 	// the addresses are known and trampolines can be inserted
 	// when necessary.
-	ctxt.Textp2 = append(stubs, ctxt.Textp2...)
+	ctxt.Textp = append(stubs, ctxt.Textp...)
 }
 
-func genaddmoduledata2(ctxt *ld.Link, ldr *loader.Loader) {
+func genaddmoduledata(ctxt *ld.Link, ldr *loader.Loader) {
 	initfunc, addmoduledata := ld.PrepareAddmoduledata(ctxt)
 	if initfunc == nil {
 		return
@@ -152,7 +151,7 @@
 	}
 
 	// addis r2, r12, .TOC.-func@ha
-	toc := ctxt.DotTOC2[0]
+	toc := ctxt.DotTOC[0]
 	rel1 := loader.Reloc{
 		Off:  0,
 		Size: 8,
@@ -207,26 +206,26 @@
 	o(0x4e800020)
 }
 
-func gentext2(ctxt *ld.Link, ldr *loader.Loader) {
+func gentext(ctxt *ld.Link, ldr *loader.Loader) {
 	if ctxt.DynlinkingGo() {
-		genaddmoduledata2(ctxt, ldr)
+		genaddmoduledata(ctxt, ldr)
 	}
 
 	if ctxt.LinkMode == ld.LinkInternal {
-		genplt2(ctxt, ldr)
+		genplt(ctxt, ldr)
 	}
 }
 
 // Construct a call stub in stub that calls symbol targ via its PLT
 // entry.
-func gencallstub2(ctxt *ld.Link, ldr *loader.Loader, abicase int, stub *loader.SymbolBuilder, targ loader.Sym) {
+func gencallstub(ctxt *ld.Link, ldr *loader.Loader, abicase int, stub *loader.SymbolBuilder, targ loader.Sym) {
 	if abicase != 1 {
 		// If we see R_PPC64_TOCSAVE or R_PPC64_REL24_NOTOC
 		// relocations, we'll need to implement cases 2 and 3.
 		log.Fatalf("gencallstub only implements case 1 calls")
 	}
 
-	plt := ctxt.PLT2
+	plt := ctxt.PLT
 
 	stub.SetType(sym.STEXT)
 
@@ -267,16 +266,16 @@
 	stub.AddUint32(ctxt.Arch, 0x4e800420) // bctr
 }
 
-func adddynrel2(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym, r loader.Reloc2, rIdx int) bool {
+func adddynrel(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym, r loader.Reloc2, rIdx int) bool {
 	if target.IsElf() {
-		return addelfdynrel2(target, ldr, syms, s, r, rIdx)
+		return addelfdynrel(target, ldr, syms, s, r, rIdx)
 	} else if target.IsAIX() {
-		return ld.Xcoffadddynrel2(target, ldr, syms, s, r, rIdx)
+		return ld.Xcoffadddynrel(target, ldr, syms, s, r, rIdx)
 	}
 	return false
 }
 
-func addelfdynrel2(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym, r loader.Reloc2, rIdx int) bool {
+func addelfdynrel(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym, r loader.Reloc2, rIdx int) bool {
 	targ := r.Sym()
 	var targType sym.SymKind
 	if targ != 0 {
@@ -325,9 +324,9 @@
 		su.SetRelocType(rIdx, objabi.R_ADDR)
 		if targType == sym.SDYNIMPORT {
 			// These happen in .toc sections
-			ld.Adddynsym2(ldr, target, syms, targ)
+			ld.Adddynsym(ldr, target, syms, targ)
 
-			rela := ldr.MakeSymbolUpdater(syms.Rela2)
+			rela := ldr.MakeSymbolUpdater(syms.Rela)
 			rela.AddAddrPlus(target.Arch, s, int64(r.Off()))
 			rela.AddUint64(target.Arch, ld.ELF64_R_INFO(uint32(ldr.SymDynid(targ)), uint32(elf.R_PPC64_ADDR64)))
 			rela.AddUint64(target.Arch, uint64(r.Add()))
@@ -403,22 +402,22 @@
 	return false
 }
 
-func xcoffreloc1(arch *sys.Arch, out *ld.OutBuf, s *sym.Symbol, r *sym.Reloc, sectoff int64) bool {
+func xcoffreloc1(arch *sys.Arch, out *ld.OutBuf, ldr *loader.Loader, s loader.Sym, r loader.ExtRelocView, sectoff int64) bool {
 	rs := r.Xsym
 
 	emitReloc := func(v uint16, off uint64) {
 		out.Write64(uint64(sectoff) + off)
-		out.Write32(uint32(rs.Dynid))
+		out.Write32(uint32(ldr.SymDynid(rs)))
 		out.Write16(v)
 	}
 
 	var v uint16
-	switch r.Type {
+	switch r.Type() {
 	default:
 		return false
-	case objabi.R_ADDR:
+	case objabi.R_ADDR, objabi.R_DWARFSECREF:
 		v = ld.XCOFF_R_POS
-		if r.Siz == 4 {
+		if r.Siz() == 4 {
 			v |= 0x1F << 8
 		} else {
 			v |= 0x3F << 8
@@ -431,21 +430,21 @@
 	case objabi.R_POWER_TLS_LE:
 		emitReloc(ld.XCOFF_R_TLS_LE|0x0F<<8, 2)
 	case objabi.R_CALLPOWER:
-		if r.Siz != 4 {
+		if r.Siz() != 4 {
 			return false
 		}
 		emitReloc(ld.XCOFF_R_RBR|0x19<<8, 0)
 	case objabi.R_XCOFFREF:
 		emitReloc(ld.XCOFF_R_REF|0x3F<<8, 0)
-
 	}
 	return true
 
 }
 
-func elfreloc1(ctxt *ld.Link, r *sym.Reloc, sectoff int64) bool {
+func elfreloc1(ctxt *ld.Link, ldr *loader.Loader, s loader.Sym, r loader.ExtRelocView, sectoff int64) bool {
 	// Beware that bit0~bit15 start from the third byte of a instruction in Big-Endian machines.
-	if r.Type == objabi.R_ADDR || r.Type == objabi.R_POWER_TLS || r.Type == objabi.R_CALLPOWER {
+	rt := r.Type()
+	if rt == objabi.R_ADDR || rt == objabi.R_POWER_TLS || rt == objabi.R_CALLPOWER {
 	} else {
 		if ctxt.Arch.ByteOrder == binary.BigEndian {
 			sectoff += 2
@@ -454,11 +453,11 @@
 	ctxt.Out.Write64(uint64(sectoff))
 
 	elfsym := ld.ElfSymForReloc(ctxt, r.Xsym)
-	switch r.Type {
+	switch rt {
 	default:
 		return false
 	case objabi.R_ADDR, objabi.R_DWARFSECREF:
-		switch r.Siz {
+		switch r.Siz() {
 		case 4:
 			ctxt.Out.Write64(uint64(elf.R_PPC64_ADDR32) | uint64(elfsym)<<32)
 		case 8:
@@ -507,7 +506,7 @@
 		ctxt.Out.Write64(uint64(sectoff + 4))
 		ctxt.Out.Write64(uint64(elf.R_PPC64_TOC16_LO_DS) | uint64(elfsym)<<32)
 	case objabi.R_CALLPOWER:
-		if r.Siz != 4 {
+		if r.Siz() != 4 {
 			return false
 		}
 		ctxt.Out.Write64(uint64(elf.R_PPC64_REL24) | uint64(elfsym)<<32)
@@ -528,24 +527,24 @@
 	}
 }
 
-func machoreloc1(arch *sys.Arch, out *ld.OutBuf, s *sym.Symbol, r *sym.Reloc, sectoff int64) bool {
+func machoreloc1(*sys.Arch, *ld.OutBuf, *loader.Loader, loader.Sym, loader.ExtRelocView, int64) bool {
 	return false
 }
 
 // Return the value of .TOC. for symbol s
-func symtoc(syms *ld.ArchSyms, s *sym.Symbol) int64 {
-	v := s.Version
-	if s.Outer != nil {
-		v = s.Outer.Version
+func symtoc(ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym) int64 {
+	v := ldr.SymVersion(s)
+	if out := ldr.OuterSym(s); out != 0 {
+		v = ldr.SymVersion(out)
 	}
 
 	toc := syms.DotTOC[v]
-	if toc == nil {
-		ld.Errorf(s, "TOC-relative relocation in object without .TOC.")
+	if toc == 0 {
+		ldr.Errorf(s, "TOC-relative relocation in object without .TOC.")
 		return 0
 	}
 
-	return toc.Value
+	return ldr.SymValue(toc)
 }
 
 // archreloctoc relocates a TOC relative symbol.
@@ -553,36 +552,35 @@
 // default load instruction can be changed to an addi instruction and the
 // symbol address can be used directly.
 // This code is for AIX only.
-func archreloctoc(target *ld.Target, syms *ld.ArchSyms, r *sym.Reloc, s *sym.Symbol, val int64) int64 {
+func archreloctoc(ldr *loader.Loader, target *ld.Target, syms *ld.ArchSyms, r loader.Reloc2, s loader.Sym, val int64) int64 {
+	rs := ldr.ResolveABIAlias(r.Sym())
 	if target.IsLinux() {
-		ld.Errorf(s, "archrelocaddr called for %s relocation\n", r.Sym.Name)
+		ldr.Errorf(s, "archrelocaddr called for %s relocation\n", ldr.SymName(rs))
 	}
 	var o1, o2 uint32
 
 	o1 = uint32(val >> 32)
 	o2 = uint32(val)
 
+	if !strings.HasPrefix(ldr.SymName(rs), "TOC.") {
+		ldr.Errorf(s, "archreloctoc called for a symbol without TOC anchor")
+	}
 	var t int64
 	useAddi := false
-	const prefix = "TOC."
-	var tarSym *sym.Symbol
-	if strings.HasPrefix(r.Sym.Name, prefix) {
-		tarSym = r.Sym.R[0].Sym
-	} else {
-		ld.Errorf(s, "archreloctoc called for a symbol without TOC anchor")
-	}
+	relocs := ldr.Relocs(rs)
+	tarSym := ldr.ResolveABIAlias(relocs.At2(0).Sym())
 
-	if target.IsInternal() && tarSym != nil && tarSym.Attr.Reachable() && (tarSym.Sect.Seg == &ld.Segdata) {
-		t = ld.Symaddr(tarSym) + r.Add - syms.TOC.Value
+	if target.IsInternal() && tarSym != 0 && ldr.AttrReachable(tarSym) && ldr.SymSect(tarSym).Seg == &ld.Segdata {
+		t = ldr.SymValue(tarSym) + r.Add() - ldr.SymValue(syms.TOC)
 		// change ld to addi in the second instruction
 		o2 = (o2 & 0x03FF0000) | 0xE<<26
 		useAddi = true
 	} else {
-		t = ld.Symaddr(r.Sym) + r.Add - syms.TOC.Value
+		t = ldr.SymValue(rs) + r.Add() - ldr.SymValue(syms.TOC)
 	}
 
 	if t != int64(int32(t)) {
-		ld.Errorf(s, "TOC relocation for %s is too big to relocate %s: 0x%x", s.Name, r.Sym, t)
+		ldr.Errorf(s, "TOC relocation for %s is too big to relocate %s: 0x%x", ldr.SymName(s), rs, t)
 	}
 
 	if t&0x8000 != 0 {
@@ -591,13 +589,13 @@
 
 	o1 |= uint32((t >> 16) & 0xFFFF)
 
-	switch r.Type {
+	switch r.Type() {
 	case objabi.R_ADDRPOWER_TOCREL_DS:
 		if useAddi {
 			o2 |= uint32(t) & 0xFFFF
 		} else {
 			if t&3 != 0 {
-				ld.Errorf(s, "bad DS reloc for %s: %d", s.Name, ld.Symaddr(r.Sym))
+				ldr.Errorf(s, "bad DS reloc for %s: %d", ldr.SymName(s), ldr.SymValue(rs))
 			}
 			o2 |= uint32(t) & 0xFFFC
 		}
@@ -610,9 +608,10 @@
 
 // archrelocaddr relocates a symbol address.
 // This code is for AIX only.
-func archrelocaddr(target *ld.Target, syms *ld.ArchSyms, r *sym.Reloc, s *sym.Symbol, val int64) int64 {
+func archrelocaddr(ldr *loader.Loader, target *ld.Target, syms *ld.ArchSyms, r loader.Reloc2, s loader.Sym, val int64) int64 {
+	rs := ldr.ResolveABIAlias(r.Sym())
 	if target.IsAIX() {
-		ld.Errorf(s, "archrelocaddr called for %s relocation\n", r.Sym.Name)
+		ldr.Errorf(s, "archrelocaddr called for %s relocation\n", ldr.SymName(rs))
 	}
 	var o1, o2 uint32
 	if target.IsBigEndian() {
@@ -630,22 +629,22 @@
 	// instruction (it is an error in this case if the low 2 bits of the address
 	// are non-zero).
 
-	t := ld.Symaddr(r.Sym) + r.Add
+	t := ldr.SymAddr(rs) + r.Add()
 	if t < 0 || t >= 1<<31 {
-		ld.Errorf(s, "relocation for %s is too big (>=2G): 0x%x", s.Name, ld.Symaddr(r.Sym))
+		ldr.Errorf(s, "relocation for %s is too big (>=2G): 0x%x", ldr.SymName(s), ldr.SymValue(rs))
 	}
 	if t&0x8000 != 0 {
 		t += 0x10000
 	}
 
-	switch r.Type {
+	switch r.Type() {
 	case objabi.R_ADDRPOWER:
 		o1 |= (uint32(t) >> 16) & 0xffff
 		o2 |= uint32(t) & 0xffff
 	case objabi.R_ADDRPOWER_DS:
 		o1 |= (uint32(t) >> 16) & 0xffff
 		if t&3 != 0 {
-			ld.Errorf(s, "bad DS reloc for %s: %d", s.Name, ld.Symaddr(r.Sym))
+			ldr.Errorf(s, "bad DS reloc for %s: %d", ldr.SymName(s), ldr.SymValue(rs))
 		}
 		o2 |= uint32(t) & 0xfffc
 	default:
@@ -799,119 +798,114 @@
 	tramp.SetData(P)
 }
 
-func archreloc(target *ld.Target, syms *ld.ArchSyms, r *sym.Reloc, s *sym.Symbol, val int64) (int64, bool) {
+func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loader.Reloc2, rr *loader.ExtReloc, s loader.Sym, val int64) (relocatedOffset int64, needExtReloc bool, ok bool) {
+	needExternal := false
+	rs := ldr.ResolveABIAlias(r.Sym())
 	if target.IsExternal() {
 		// On AIX, relocations (except TLS ones) must be also done to the
 		// value with the current addresses.
-		switch r.Type {
+		switch r.Type() {
 		default:
 			if target.IsAIX() {
-				return val, false
+				return val, needExternal, false
 			}
 		case objabi.R_POWER_TLS, objabi.R_POWER_TLS_LE, objabi.R_POWER_TLS_IE:
-			r.Done = false
 			// check Outer is nil, Type is TLSBSS?
-			r.Xadd = r.Add
-			r.Xsym = r.Sym
-			return val, true
+			needExternal = true
+			rr.Xadd = r.Add()
+			rr.Xsym = rs
+			return val, needExternal, true
 		case objabi.R_ADDRPOWER,
 			objabi.R_ADDRPOWER_DS,
 			objabi.R_ADDRPOWER_TOCREL,
 			objabi.R_ADDRPOWER_TOCREL_DS,
 			objabi.R_ADDRPOWER_GOT,
 			objabi.R_ADDRPOWER_PCREL:
-			r.Done = false
+			needExternal = true
 
 			// set up addend for eventual relocation via outer symbol.
-			rs := r.Sym
-			r.Xadd = r.Add
-			for rs.Outer != nil {
-				r.Xadd += ld.Symaddr(rs) - ld.Symaddr(rs.Outer)
-				rs = rs.Outer
+			rs, off := ld.FoldSubSymbolOffset(ldr, rs)
+			rr.Xadd = r.Add() + off
+			rst := ldr.SymType(rs)
+			if rst != sym.SHOSTOBJ && rst != sym.SDYNIMPORT && rst != sym.SUNDEFEXT && ldr.SymSect(rs) == nil {
+				ldr.Errorf(s, "missing section for %s", ldr.SymName(rs))
 			}
-
-			if rs.Type != sym.SHOSTOBJ && rs.Type != sym.SDYNIMPORT && rs.Type != sym.SUNDEFEXT && rs.Sect == nil {
-				ld.Errorf(s, "missing section for %s", rs.Name)
-			}
-			r.Xsym = rs
+			rr.Xsym = rs
 
 			if !target.IsAIX() {
-				return val, true
+				return val, needExternal, true
 			}
 		case objabi.R_CALLPOWER:
-			r.Done = false
-			r.Xsym = r.Sym
-			r.Xadd = r.Add
+			needExternal = true
+			rr.Xsym = rs
+			rr.Xadd = r.Add()
 			if !target.IsAIX() {
-				return val, true
+				return val, needExternal, true
 			}
 		}
 	}
 
-	switch r.Type {
-	case objabi.R_CONST:
-		return r.Add, true
-	case objabi.R_GOTOFF:
-		return ld.Symaddr(r.Sym) + r.Add - ld.Symaddr(syms.GOT), true
+	switch r.Type() {
 	case objabi.R_ADDRPOWER_TOCREL, objabi.R_ADDRPOWER_TOCREL_DS:
-		return archreloctoc(target, syms, r, s, val), true
+		return archreloctoc(ldr, target, syms, r, s, val), needExternal, true
 	case objabi.R_ADDRPOWER, objabi.R_ADDRPOWER_DS:
-		return archrelocaddr(target, syms, r, s, val), true
+		return archrelocaddr(ldr, target, syms, r, s, val), needExternal, true
 	case objabi.R_CALLPOWER:
 		// Bits 6 through 29 = (S + A - P) >> 2
 
-		t := ld.Symaddr(r.Sym) + r.Add - (s.Value + int64(r.Off))
+		t := ldr.SymValue(rs) + r.Add() - (ldr.SymValue(s) + int64(r.Off()))
 
 		if t&3 != 0 {
-			ld.Errorf(s, "relocation for %s+%d is not aligned: %d", r.Sym.Name, r.Off, t)
+			ldr.Errorf(s, "relocation for %s+%d is not aligned: %d", ldr.SymName(rs), r.Off(), t)
 		}
 		// If branch offset is too far then create a trampoline.
 
 		if int64(int32(t<<6)>>6) != t {
-			ld.Errorf(s, "direct call too far: %s %x", r.Sym.Name, t)
+			ldr.Errorf(s, "direct call too far: %s %x", ldr.SymName(rs), t)
 		}
-		return val | int64(uint32(t)&^0xfc000003), true
+		return val | int64(uint32(t)&^0xfc000003), needExternal, true
 	case objabi.R_POWER_TOC: // S + A - .TOC.
-		return ld.Symaddr(r.Sym) + r.Add - symtoc(syms, s), true
+		return ldr.SymValue(rs) + r.Add() - symtoc(ldr, syms, s), needExternal, true
 
 	case objabi.R_POWER_TLS_LE:
 		// The thread pointer points 0x7000 bytes after the start of the
 		// thread local storage area as documented in section "3.7.2 TLS
 		// Runtime Handling" of "Power Architecture 64-Bit ELF V2 ABI
 		// Specification".
-		v := r.Sym.Value - 0x7000
+		v := ldr.SymValue(rs) - 0x7000
 		if target.IsAIX() {
 			// On AIX, the thread pointer points 0x7800 bytes after
 			// the TLS.
 			v -= 0x800
 		}
 		if int64(int16(v)) != v {
-			ld.Errorf(s, "TLS offset out of range %d", v)
+			ldr.Errorf(s, "TLS offset out of range %d", v)
 		}
-		return (val &^ 0xffff) | (v & 0xffff), true
+		return (val &^ 0xffff) | (v & 0xffff), needExternal, true
 	}
 
-	return val, false
+	return val, needExternal, false
 }
 
-func archrelocvariant(target *ld.Target, syms *ld.ArchSyms, r *sym.Reloc, s *sym.Symbol, t int64) int64 {
-	switch r.Variant & sym.RV_TYPE_MASK {
+func archrelocvariant(target *ld.Target, ldr *loader.Loader, r loader.Reloc2, rv sym.RelocVariant, s loader.Sym, t int64) (relocatedOffset int64) {
+	rs := ldr.ResolveABIAlias(r.Sym())
+	switch rv & sym.RV_TYPE_MASK {
 	default:
-		ld.Errorf(s, "unexpected relocation variant %d", r.Variant)
+		ldr.Errorf(s, "unexpected relocation variant %d", rv)
 		fallthrough
 
 	case sym.RV_NONE:
 		return t
 
 	case sym.RV_POWER_LO:
-		if r.Variant&sym.RV_CHECK_OVERFLOW != 0 {
+		if rv&sym.RV_CHECK_OVERFLOW != 0 {
 			// Whether to check for signed or unsigned
 			// overflow depends on the instruction
 			var o1 uint32
 			if target.IsBigEndian() {
-				o1 = binary.BigEndian.Uint32(s.P[r.Off-2:])
+				o1 = binary.BigEndian.Uint32(ldr.Data(s)[r.Off()-2:])
 			} else {
-				o1 = binary.LittleEndian.Uint32(s.P[r.Off:])
+				o1 = binary.LittleEndian.Uint32(ldr.Data(s)[r.Off():])
 			}
 			switch o1 >> 26 {
 			case 24, // ori
@@ -938,14 +932,14 @@
 	case sym.RV_POWER_HI:
 		t >>= 16
 
-		if r.Variant&sym.RV_CHECK_OVERFLOW != 0 {
+		if rv&sym.RV_CHECK_OVERFLOW != 0 {
 			// Whether to check for signed or unsigned
 			// overflow depends on the instruction
 			var o1 uint32
 			if target.IsBigEndian() {
-				o1 = binary.BigEndian.Uint32(s.P[r.Off-2:])
+				o1 = binary.BigEndian.Uint32(ldr.Data(s)[r.Off()-2:])
 			} else {
-				o1 = binary.LittleEndian.Uint32(s.P[r.Off:])
+				o1 = binary.LittleEndian.Uint32(ldr.Data(s)[r.Off():])
 			}
 			switch o1 >> 26 {
 			case 25, // oris
@@ -967,40 +961,40 @@
 	case sym.RV_POWER_DS:
 		var o1 uint32
 		if target.IsBigEndian() {
-			o1 = uint32(binary.BigEndian.Uint16(s.P[r.Off:]))
+			o1 = uint32(binary.BigEndian.Uint16(ldr.Data(s)[r.Off():]))
 		} else {
-			o1 = uint32(binary.LittleEndian.Uint16(s.P[r.Off:]))
+			o1 = uint32(binary.LittleEndian.Uint16(ldr.Data(s)[r.Off():]))
 		}
 		if t&3 != 0 {
-			ld.Errorf(s, "relocation for %s+%d is not aligned: %d", r.Sym.Name, r.Off, t)
+			ldr.Errorf(s, "relocation for %s+%d is not aligned: %d", ldr.SymName(rs), r.Off(), t)
 		}
-		if (r.Variant&sym.RV_CHECK_OVERFLOW != 0) && int64(int16(t)) != t {
+		if (rv&sym.RV_CHECK_OVERFLOW != 0) && int64(int16(t)) != t {
 			goto overflow
 		}
 		return int64(o1)&0x3 | int64(int16(t))
 	}
 
 overflow:
-	ld.Errorf(s, "relocation for %s+%d is too big: %d", r.Sym.Name, r.Off, t)
+	ldr.Errorf(s, "relocation for %s+%d is too big: %d", ldr.SymName(rs), r.Off(), t)
 	return t
 }
 
-func addpltsym2(ctxt *ld.Link, ldr *loader.Loader, s loader.Sym) {
+func addpltsym(ctxt *ld.Link, ldr *loader.Loader, s loader.Sym) {
 	if ldr.SymPlt(s) >= 0 {
 		return
 	}
 
-	ld.Adddynsym2(ldr, &ctxt.Target, &ctxt.ArchSyms, s)
+	ld.Adddynsym(ldr, &ctxt.Target, &ctxt.ArchSyms, s)
 
 	if ctxt.IsELF {
-		plt := ldr.MakeSymbolUpdater(ctxt.PLT2)
-		rela := ldr.MakeSymbolUpdater(ctxt.RelaPLT2)
+		plt := ldr.MakeSymbolUpdater(ctxt.PLT)
+		rela := ldr.MakeSymbolUpdater(ctxt.RelaPLT)
 		if plt.Size() == 0 {
 			panic("plt is not set up")
 		}
 
 		// Create the glink resolver if necessary
-		glink := ensureglinkresolver2(ctxt, ldr)
+		glink := ensureglinkresolver(ctxt, ldr)
 
 		// Write symbol resolver stub (just a branch to the
 		// glink resolver stub)
@@ -1032,7 +1026,7 @@
 }
 
 // Generate the glink resolver stub if necessary and return the .glink section
-func ensureglinkresolver2(ctxt *ld.Link, ldr *loader.Loader) *loader.SymbolBuilder {
+func ensureglinkresolver(ctxt *ld.Link, ldr *loader.Loader) *loader.SymbolBuilder {
 	gs := ldr.LookupOrCreateSym(".glink", 0)
 	glink := ldr.MakeSymbolUpdater(gs)
 	if glink.Size() != 0 {
@@ -1061,7 +1055,7 @@
 	glink.AddUint32(ctxt.Arch, 0x7800f082) // srdi r0,r0,2
 
 	// r11 = address of the first byte of the PLT
-	glink.AddSymRef(ctxt.Arch, ctxt.PLT2, 0, objabi.R_ADDRPOWER, 8)
+	glink.AddSymRef(ctxt.Arch, ctxt.PLT, 0, objabi.R_ADDRPOWER, 8)
 
 	glink.AddUint32(ctxt.Arch, 0x3d600000) // addis r11,0,.plt@ha
 	glink.AddUint32(ctxt.Arch, 0x396b0000) // addi r11,r11,.plt@l
@@ -1080,121 +1074,8 @@
 
 	// Add DT_PPC64_GLINK .dynamic entry, which points to 32 bytes
 	// before the first symbol resolver stub.
-	du := ldr.MakeSymbolUpdater(ctxt.Dynamic2)
-	ld.Elfwritedynentsymplus2(ctxt, du, ld.DT_PPC64_GLINK, glink.Sym(), glink.Size()-32)
+	du := ldr.MakeSymbolUpdater(ctxt.Dynamic)
+	ld.Elfwritedynentsymplus(ctxt, du, ld.DT_PPC64_GLINK, glink.Sym(), glink.Size()-32)
 
 	return glink
 }
-
-func asmb(ctxt *ld.Link, _ *loader.Loader) {
-	if ctxt.IsELF {
-		ld.Asmbelfsetup()
-	}
-
-	var wg sync.WaitGroup
-	for _, sect := range ld.Segtext.Sections {
-		offset := sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff
-		// Handle additional text sections with Codeblk
-		if sect.Name == ".text" {
-			ld.WriteParallel(&wg, ld.Codeblk, ctxt, offset, sect.Vaddr, sect.Length)
-		} else {
-			ld.WriteParallel(&wg, ld.Datblk, ctxt, offset, sect.Vaddr, sect.Length)
-		}
-	}
-
-	if ld.Segrodata.Filelen > 0 {
-		ld.WriteParallel(&wg, ld.Datblk, ctxt, ld.Segrodata.Fileoff, ld.Segrodata.Vaddr, ld.Segrodata.Filelen)
-	}
-
-	if ld.Segrelrodata.Filelen > 0 {
-		ld.WriteParallel(&wg, ld.Datblk, ctxt, ld.Segrelrodata.Fileoff, ld.Segrelrodata.Vaddr, ld.Segrelrodata.Filelen)
-	}
-
-	ld.WriteParallel(&wg, ld.Datblk, ctxt, ld.Segdata.Fileoff, ld.Segdata.Vaddr, ld.Segdata.Filelen)
-
-	ld.WriteParallel(&wg, ld.Dwarfblk, ctxt, ld.Segdwarf.Fileoff, ld.Segdwarf.Vaddr, ld.Segdwarf.Filelen)
-	wg.Wait()
-}
-
-func asmb2(ctxt *ld.Link) {
-	/* output symbol table */
-	ld.Symsize = 0
-
-	ld.Lcsize = 0
-	symo := uint32(0)
-	if !*ld.FlagS {
-		// TODO: rationalize
-		switch ctxt.HeadType {
-		default:
-			if ctxt.IsELF {
-				symo = uint32(ld.Segdwarf.Fileoff + ld.Segdwarf.Filelen)
-				symo = uint32(ld.Rnd(int64(symo), int64(*ld.FlagRound)))
-			}
-
-		case objabi.Hplan9:
-			symo = uint32(ld.Segdata.Fileoff + ld.Segdata.Filelen)
-
-		case objabi.Haix:
-			// Nothing to do
-		}
-
-		ctxt.Out.SeekSet(int64(symo))
-		switch ctxt.HeadType {
-		default:
-			if ctxt.IsELF {
-				ld.Asmelfsym(ctxt)
-				ctxt.Out.Write(ld.Elfstrdat)
-
-				if ctxt.LinkMode == ld.LinkExternal {
-					ld.Elfemitreloc(ctxt)
-				}
-			}
-
-		case objabi.Hplan9:
-			ld.Asmplan9sym(ctxt)
-
-			sym := ctxt.Syms.Lookup("pclntab", 0)
-			if sym != nil {
-				ld.Lcsize = int32(len(sym.P))
-				ctxt.Out.Write(sym.P)
-			}
-
-		case objabi.Haix:
-			// symtab must be added once sections have been created in ld.Asmbxcoff
-		}
-	}
-
-	ctxt.Out.SeekSet(0)
-	switch ctxt.HeadType {
-	default:
-	case objabi.Hplan9: /* plan 9 */
-		ctxt.Out.Write32(0x647)                      /* magic */
-		ctxt.Out.Write32(uint32(ld.Segtext.Filelen)) /* sizes */
-		ctxt.Out.Write32(uint32(ld.Segdata.Filelen))
-		ctxt.Out.Write32(uint32(ld.Segdata.Length - ld.Segdata.Filelen))
-		ctxt.Out.Write32(uint32(ld.Symsize))          /* nsyms */
-		ctxt.Out.Write32(uint32(ld.Entryvalue(ctxt))) /* va of entry */
-		ctxt.Out.Write32(0)
-		ctxt.Out.Write32(uint32(ld.Lcsize))
-
-	case objabi.Hlinux,
-		objabi.Hfreebsd,
-		objabi.Hnetbsd,
-		objabi.Hopenbsd:
-		ld.Asmbelf(ctxt, int64(symo))
-
-	case objabi.Haix:
-		fileoff := uint32(ld.Segdwarf.Fileoff + ld.Segdwarf.Filelen)
-		fileoff = uint32(ld.Rnd(int64(fileoff), int64(*ld.FlagRound)))
-		ld.Asmbxcoff(ctxt, int64(fileoff))
-	}
-
-	if *ld.FlagC {
-		fmt.Printf("textsize=%d\n", ld.Segtext.Filelen)
-		fmt.Printf("datsize=%d\n", ld.Segdata.Filelen)
-		fmt.Printf("bsssize=%d\n", ld.Segdata.Length-ld.Segdata.Filelen)
-		fmt.Printf("symsize=%d\n", ld.Symsize)
-		fmt.Printf("lcsize=%d\n", ld.Lcsize)
-		fmt.Printf("total=%d\n", ld.Segtext.Filelen+ld.Segdata.Length+uint64(ld.Symsize)+uint64(ld.Lcsize))
-	}
-}
diff --git a/src/cmd/link/internal/ppc64/obj.go b/src/cmd/link/internal/ppc64/obj.go
index 3e1d0a1..8a94f9a 100644
--- a/src/cmd/link/internal/ppc64/obj.go
+++ b/src/cmd/link/internal/ppc64/obj.go
@@ -43,21 +43,20 @@
 	}
 
 	theArch := ld.Arch{
-		Funcalign:  funcAlign,
-		Maxalign:   maxAlign,
-		Minalign:   minAlign,
-		Dwarfregsp: dwarfRegSP,
-		Dwarfreglr: dwarfRegLR,
+		Funcalign:       funcAlign,
+		Maxalign:        maxAlign,
+		Minalign:        minAlign,
+		Dwarfregsp:      dwarfRegSP,
+		Dwarfreglr:      dwarfRegLR,
+		WriteTextBlocks: true,
 
-		Adddynrel2:       adddynrel2,
+		Adddynrel:        adddynrel,
 		Archinit:         archinit,
 		Archreloc:        archreloc,
 		Archrelocvariant: archrelocvariant,
-		Asmb:             asmb,
-		Asmb2:            asmb2,
 		Elfreloc1:        elfreloc1,
 		Elfsetupplt:      elfsetupplt,
-		Gentext2:         gentext2,
+		Gentext:          gentext,
 		Trampoline:       trampoline,
 		Machoreloc1:      machoreloc1,
 		Xcoffreloc1:      xcoffreloc1,
diff --git a/src/cmd/link/internal/riscv64/asm.go b/src/cmd/link/internal/riscv64/asm.go
index 5183de8..7bc511c 100644
--- a/src/cmd/link/internal/riscv64/asm.go
+++ b/src/cmd/link/internal/riscv64/asm.go
@@ -13,23 +13,13 @@
 	"cmd/link/internal/sym"
 	"fmt"
 	"log"
-	"sync"
 )
 
-func gentext2(ctxt *ld.Link, ldr *loader.Loader) {
+func gentext(ctxt *ld.Link, ldr *loader.Loader) {
 }
 
-func adddynrela(target *ld.Target, syms *ld.ArchSyms, rel *sym.Symbol, s *sym.Symbol, r *sym.Reloc) {
-	log.Fatalf("adddynrela not implemented")
-}
-
-func adddynrel(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s *sym.Symbol, r *sym.Reloc) bool {
-	log.Fatalf("adddynrel not implemented")
-	return false
-}
-
-func elfreloc1(ctxt *ld.Link, r *sym.Reloc, sectoff int64) bool {
-	log.Fatalf("elfreloc1")
+func elfreloc1(ctxt *ld.Link, ldr *loader.Loader, s loader.Sym, r loader.ExtRelocView, sectoff int64) bool {
+	log.Fatalf("elfreloc2")
 	return false
 }
 
@@ -37,48 +27,50 @@
 	log.Fatalf("elfsetuplt")
 }
 
-func machoreloc1(arch *sys.Arch, out *ld.OutBuf, s *sym.Symbol, r *sym.Reloc, sectoff int64) bool {
+func machoreloc1(*sys.Arch, *ld.OutBuf, *loader.Loader, loader.Sym, loader.ExtRelocView, int64) bool {
 	log.Fatalf("machoreloc1 not implemented")
 	return false
 }
 
-func archreloc(target *ld.Target, syms *ld.ArchSyms, r *sym.Reloc, s *sym.Symbol, val int64) (int64, bool) {
-	switch r.Type {
+func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loader.Reloc2, rr *loader.ExtReloc, s loader.Sym, val int64) (o int64, needExtReloc bool, ok bool) {
+	rs := r.Sym()
+	rs = ldr.ResolveABIAlias(rs)
+	switch r.Type() {
 	case objabi.R_CALLRISCV:
 		// Nothing to do.
-		return val, true
+		return val, false, true
 
 	case objabi.R_RISCV_PCREL_ITYPE, objabi.R_RISCV_PCREL_STYPE:
-		pc := s.Value + int64(r.Off)
-		off := ld.Symaddr(r.Sym) + r.Add - pc
+		pc := ldr.SymValue(s) + int64(r.Off())
+		off := ldr.SymValue(rs) + r.Add() - pc
 
 		// Generate AUIPC and second instruction immediates.
 		low, high, err := riscv.Split32BitImmediate(off)
 		if err != nil {
-			ld.Errorf(s, "R_RISCV_PCREL_ relocation does not fit in 32-bits: %d", off)
+			ldr.Errorf(s, "R_RISCV_PCREL_ relocation does not fit in 32-bits: %d", off)
 		}
 
 		auipcImm, err := riscv.EncodeUImmediate(high)
 		if err != nil {
-			ld.Errorf(s, "cannot encode R_RISCV_PCREL_ AUIPC relocation offset for %s: %v", r.Sym.Name, err)
+			ldr.Errorf(s, "cannot encode R_RISCV_PCREL_ AUIPC relocation offset for %s: %v", ldr.SymName(rs), err)
 		}
 
 		var secondImm, secondImmMask int64
-		switch r.Type {
+		switch r.Type() {
 		case objabi.R_RISCV_PCREL_ITYPE:
 			secondImmMask = riscv.ITypeImmMask
 			secondImm, err = riscv.EncodeIImmediate(low)
 			if err != nil {
-				ld.Errorf(s, "cannot encode R_RISCV_PCREL_ITYPE I-type instruction relocation offset for %s: %v", r.Sym.Name, err)
+				ldr.Errorf(s, "cannot encode R_RISCV_PCREL_ITYPE I-type instruction relocation offset for %s: %v", ldr.SymName(rs), err)
 			}
 		case objabi.R_RISCV_PCREL_STYPE:
 			secondImmMask = riscv.STypeImmMask
 			secondImm, err = riscv.EncodeSImmediate(low)
 			if err != nil {
-				ld.Errorf(s, "cannot encode R_RISCV_PCREL_STYPE S-type instruction relocation offset for %s: %v", r.Sym.Name, err)
+				ldr.Errorf(s, "cannot encode R_RISCV_PCREL_STYPE S-type instruction relocation offset for %s: %v", ldr.SymName(rs), err)
 			}
 		default:
-			panic(fmt.Sprintf("Unknown relocation type: %v", r.Type))
+			panic(fmt.Sprintf("Unknown relocation type: %v", r.Type()))
 		}
 
 		auipc := int64(uint32(val))
@@ -87,82 +79,13 @@
 		auipc = (auipc &^ riscv.UTypeImmMask) | int64(uint32(auipcImm))
 		second = (second &^ secondImmMask) | int64(uint32(secondImm))
 
-		return second<<32 | auipc, true
+		return second<<32 | auipc, false, true
 	}
 
-	return val, false
+	return val, false, false
 }
 
-func archrelocvariant(target *ld.Target, syms *ld.ArchSyms, r *sym.Reloc, s *sym.Symbol, t int64) int64 {
+func archrelocvariant(*ld.Target, *loader.Loader, loader.Reloc2, sym.RelocVariant, loader.Sym, int64) int64 {
 	log.Fatalf("archrelocvariant")
 	return -1
 }
-
-func asmb(ctxt *ld.Link, _ *loader.Loader) {
-	if ctxt.IsELF {
-		ld.Asmbelfsetup()
-	}
-
-	var wg sync.WaitGroup
-	sect := ld.Segtext.Sections[0]
-	offset := sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff
-	ld.WriteParallel(&wg, ld.Codeblk, ctxt, offset, sect.Vaddr, sect.Length)
-
-	for _, sect := range ld.Segtext.Sections[1:] {
-		offset := sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff
-		ld.WriteParallel(&wg, ld.Datblk, ctxt, offset, sect.Vaddr, sect.Length)
-	}
-
-	if ld.Segrodata.Filelen > 0 {
-		ld.WriteParallel(&wg, ld.Datblk, ctxt, ld.Segrodata.Fileoff, ld.Segrodata.Vaddr, ld.Segrodata.Filelen)
-	}
-
-	if ld.Segrelrodata.Filelen > 0 {
-		ld.WriteParallel(&wg, ld.Datblk, ctxt, ld.Segrelrodata.Fileoff, ld.Segrelrodata.Vaddr, ld.Segrelrodata.Filelen)
-	}
-
-	ld.WriteParallel(&wg, ld.Datblk, ctxt, ld.Segdata.Fileoff, ld.Segdata.Vaddr, ld.Segdata.Filelen)
-
-	ld.WriteParallel(&wg, ld.Dwarfblk, ctxt, ld.Segdwarf.Fileoff, ld.Segdwarf.Vaddr, ld.Segdwarf.Filelen)
-	wg.Wait()
-}
-
-func asmb2(ctxt *ld.Link) {
-	ld.Symsize = 0
-	ld.Lcsize = 0
-	symo := uint32(0)
-
-	if !*ld.FlagS {
-		if !ctxt.IsELF {
-			ld.Errorf(nil, "unsupported executable format")
-		}
-
-		symo = uint32(ld.Segdwarf.Fileoff + ld.Segdwarf.Filelen)
-		symo = uint32(ld.Rnd(int64(symo), int64(*ld.FlagRound)))
-		ctxt.Out.SeekSet(int64(symo))
-
-		ld.Asmelfsym(ctxt)
-		ctxt.Out.Write(ld.Elfstrdat)
-
-		if ctxt.LinkMode == ld.LinkExternal {
-			ld.Elfemitreloc(ctxt)
-		}
-	}
-
-	ctxt.Out.SeekSet(0)
-	switch ctxt.HeadType {
-	case objabi.Hlinux:
-		ld.Asmbelf(ctxt, int64(symo))
-	default:
-		ld.Errorf(nil, "unsupported operating system")
-	}
-
-	if *ld.FlagC {
-		fmt.Printf("textsize=%d\n", ld.Segtext.Filelen)
-		fmt.Printf("datsize=%d\n", ld.Segdata.Filelen)
-		fmt.Printf("bsssize=%d\n", ld.Segdata.Length-ld.Segdata.Filelen)
-		fmt.Printf("symsize=%d\n", ld.Symsize)
-		fmt.Printf("lcsize=%d\n", ld.Lcsize)
-		fmt.Printf("total=%d\n", ld.Segtext.Filelen+ld.Segdata.Length+uint64(ld.Symsize)+uint64(ld.Lcsize))
-	}
-}
diff --git a/src/cmd/link/internal/riscv64/obj.go b/src/cmd/link/internal/riscv64/obj.go
index 4fa0ebe..e66d3cd 100644
--- a/src/cmd/link/internal/riscv64/obj.go
+++ b/src/cmd/link/internal/riscv64/obj.go
@@ -20,15 +20,12 @@
 		Dwarfregsp: dwarfRegSP,
 		Dwarfreglr: dwarfRegLR,
 
-		Adddynrel:        adddynrel,
 		Archinit:         archinit,
 		Archreloc:        archreloc,
 		Archrelocvariant: archrelocvariant,
-		Asmb:             asmb,
-		Asmb2:            asmb2,
 		Elfreloc1:        elfreloc1,
 		Elfsetupplt:      elfsetupplt,
-		Gentext2:         gentext2,
+		Gentext:          gentext,
 		Machoreloc1:      machoreloc1,
 
 		Linuxdynld: "/lib/ld.so.1",
diff --git a/src/cmd/link/internal/s390x/asm.go b/src/cmd/link/internal/s390x/asm.go
index 2115b5f..11406ee 100644
--- a/src/cmd/link/internal/s390x/asm.go
+++ b/src/cmd/link/internal/s390x/asm.go
@@ -37,8 +37,6 @@
 	"cmd/link/internal/loader"
 	"cmd/link/internal/sym"
 	"debug/elf"
-	"fmt"
-	"sync"
 )
 
 // gentext generates assembly to append the local moduledata to the global
@@ -51,7 +49,7 @@
 //	undef
 //
 // The job of appending the moduledata is delegated to runtime.addmoduledata.
-func gentext2(ctxt *ld.Link, ldr *loader.Loader) {
+func gentext(ctxt *ld.Link, ldr *loader.Loader) {
 	initfunc, addmoduledata := ld.PrepareAddmoduledata(ctxt)
 	if initfunc == nil {
 		return
@@ -60,7 +58,7 @@
 	// larl %r2, <local.moduledata>
 	initfunc.AddUint8(0xc0)
 	initfunc.AddUint8(0x20)
-	initfunc.AddSymRef(ctxt.Arch, ctxt.Moduledata2, 6, objabi.R_PCREL, 4)
+	initfunc.AddSymRef(ctxt.Arch, ctxt.Moduledata, 6, objabi.R_PCREL, 4)
 	r1 := initfunc.Relocs()
 	ldr.SetRelocVariant(initfunc.Sym(), r1.Count()-1, sym.RV_390_DBL)
 
@@ -75,7 +73,7 @@
 	initfunc.AddUint32(ctxt.Arch, 0)
 }
 
-func adddynrel2(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym, r loader.Reloc2, rIdx int) bool {
+func adddynrel(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym, r loader.Reloc2, rIdx int) bool {
 	targ := r.Sym()
 	var targType sym.SymKind
 	if targ != 0 {
@@ -136,8 +134,8 @@
 		ldr.SetRelocVariant(s, rIdx, sym.RV_390_DBL)
 		su.SetRelocAdd(rIdx, r.Add()+int64(r.Siz()))
 		if targType == sym.SDYNIMPORT {
-			addpltsym2(target, ldr, syms, targ)
-			r.SetSym(syms.PLT2)
+			addpltsym(target, ldr, syms, targ)
+			r.SetSym(syms.PLT)
 			su.SetRelocAdd(rIdx, r.Add()+int64(ldr.SymPlt(targ)))
 		}
 		return true
@@ -148,8 +146,8 @@
 		su.SetRelocType(rIdx, objabi.R_PCREL)
 		su.SetRelocAdd(rIdx, r.Add()+int64(r.Siz()))
 		if targType == sym.SDYNIMPORT {
-			addpltsym2(target, ldr, syms, targ)
-			r.SetSym(syms.PLT2)
+			addpltsym(target, ldr, syms, targ)
+			r.SetSym(syms.PLT)
 			su.SetRelocAdd(rIdx, r.Add()+int64(ldr.SymPlt(targ)))
 		}
 		return true
@@ -181,7 +179,7 @@
 	case objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_GOTPC):
 		su := ldr.MakeSymbolUpdater(s)
 		su.SetRelocType(rIdx, objabi.R_PCREL)
-		r.SetSym(syms.GOT2)
+		r.SetSym(syms.GOT)
 		su.SetRelocAdd(rIdx, r.Add()+int64(r.Siz()))
 		return true
 
@@ -200,16 +198,16 @@
 		su := ldr.MakeSymbolUpdater(s)
 		su.SetRelocType(rIdx, objabi.R_PCREL)
 		ldr.SetRelocVariant(s, rIdx, sym.RV_390_DBL)
-		r.SetSym(syms.GOT2)
+		r.SetSym(syms.GOT)
 		su.SetRelocAdd(rIdx, r.Add()+int64(r.Siz()))
 		return true
 
 	case objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_GOTENT):
-		addgotsym2(target, ldr, syms, targ)
+		ld.AddGotSym(target, ldr, syms, targ, uint32(elf.R_390_GLOB_DAT))
 		su := ldr.MakeSymbolUpdater(s)
 		su.SetRelocType(rIdx, objabi.R_PCREL)
 		ldr.SetRelocVariant(s, rIdx, sym.RV_390_DBL)
-		r.SetSym(syms.GOT2)
+		r.SetSym(syms.GOT)
 		su.SetRelocAdd(rIdx, r.Add()+int64(ldr.SymGot(targ))+int64(r.Siz()))
 		return true
 	}
@@ -221,15 +219,17 @@
 	return false
 }
 
-func elfreloc1(ctxt *ld.Link, r *sym.Reloc, sectoff int64) bool {
+func elfreloc1(ctxt *ld.Link, ldr *loader.Loader, s loader.Sym, r loader.ExtRelocView, sectoff int64) bool {
 	ctxt.Out.Write64(uint64(sectoff))
 
 	elfsym := ld.ElfSymForReloc(ctxt, r.Xsym)
-	switch r.Type {
+	siz := r.Siz()
+	xst := ldr.SymType(r.Xsym)
+	switch r.Type() {
 	default:
 		return false
 	case objabi.R_TLS_LE:
-		switch r.Siz {
+		switch siz {
 		default:
 			return false
 		case 4:
@@ -240,14 +240,14 @@
 			ctxt.Out.Write64(uint64(elf.R_390_TLS_LE64) | uint64(elfsym)<<32)
 		}
 	case objabi.R_TLS_IE:
-		switch r.Siz {
+		switch siz {
 		default:
 			return false
 		case 4:
 			ctxt.Out.Write64(uint64(elf.R_390_TLS_IEENT) | uint64(elfsym)<<32)
 		}
 	case objabi.R_ADDR, objabi.R_DWARFSECREF:
-		switch r.Siz {
+		switch siz {
 		default:
 			return false
 		case 4:
@@ -256,30 +256,31 @@
 			ctxt.Out.Write64(uint64(elf.R_390_64) | uint64(elfsym)<<32)
 		}
 	case objabi.R_GOTPCREL:
-		if r.Siz == 4 {
+		if siz == 4 {
 			ctxt.Out.Write64(uint64(elf.R_390_GOTENT) | uint64(elfsym)<<32)
 		} else {
 			return false
 		}
 	case objabi.R_PCREL, objabi.R_PCRELDBL, objabi.R_CALL:
 		elfrel := elf.R_390_NONE
-		isdbl := r.Variant&sym.RV_TYPE_MASK == sym.RV_390_DBL
+		rVariant := ldr.RelocVariant(s, r.Idx)
+		isdbl := rVariant&sym.RV_TYPE_MASK == sym.RV_390_DBL
 		// TODO(mundaym): all DBL style relocations should be
 		// signalled using the variant - see issue 14218.
-		switch r.Type {
+		switch r.Type() {
 		case objabi.R_PCRELDBL, objabi.R_CALL:
 			isdbl = true
 		}
-		if r.Xsym.Type == sym.SDYNIMPORT && (r.Xsym.ElfType() == elf.STT_FUNC || r.Type == objabi.R_CALL) {
+		if xst == sym.SDYNIMPORT && (ldr.SymElfType(r.Xsym) == elf.STT_FUNC || r.Type() == objabi.R_CALL) {
 			if isdbl {
-				switch r.Siz {
+				switch siz {
 				case 2:
 					elfrel = elf.R_390_PLT16DBL
 				case 4:
 					elfrel = elf.R_390_PLT32DBL
 				}
 			} else {
-				switch r.Siz {
+				switch siz {
 				case 4:
 					elfrel = elf.R_390_PLT32
 				case 8:
@@ -288,14 +289,14 @@
 			}
 		} else {
 			if isdbl {
-				switch r.Siz {
+				switch siz {
 				case 2:
 					elfrel = elf.R_390_PC16DBL
 				case 4:
 					elfrel = elf.R_390_PC32DBL
 				}
 			} else {
-				switch r.Siz {
+				switch siz {
 				case 2:
 					elfrel = elf.R_390_PC16
 				case 4:
@@ -363,53 +364,42 @@
 	}
 }
 
-func machoreloc1(arch *sys.Arch, out *ld.OutBuf, s *sym.Symbol, r *sym.Reloc, sectoff int64) bool {
+func machoreloc1(*sys.Arch, *ld.OutBuf, *loader.Loader, loader.Sym, loader.ExtRelocView, int64) bool {
 	return false
 }
 
-func archreloc(target *ld.Target, syms *ld.ArchSyms, r *sym.Reloc, s *sym.Symbol, val int64) (int64, bool) {
-	if target.IsExternal() {
-		return val, false
-	}
-
-	switch r.Type {
-	case objabi.R_CONST:
-		return r.Add, true
-	case objabi.R_GOTOFF:
-		return ld.Symaddr(r.Sym) + r.Add - ld.Symaddr(syms.GOT), true
-	}
-
-	return val, false
+func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loader.Reloc2, rr *loader.ExtReloc, s loader.Sym, val int64) (o int64, needExtReloc bool, ok bool) {
+	return val, false, false
 }
 
-func archrelocvariant(target *ld.Target, syms *ld.ArchSyms, r *sym.Reloc, s *sym.Symbol, t int64) int64 {
-	switch r.Variant & sym.RV_TYPE_MASK {
+func archrelocvariant(target *ld.Target, ldr *loader.Loader, r loader.Reloc2, rv sym.RelocVariant, s loader.Sym, t int64) int64 {
+	switch rv & sym.RV_TYPE_MASK {
 	default:
-		ld.Errorf(s, "unexpected relocation variant %d", r.Variant)
+		ldr.Errorf(s, "unexpected relocation variant %d", rv)
 		return t
 
 	case sym.RV_NONE:
 		return t
 
 	case sym.RV_390_DBL:
-		if (t & 1) != 0 {
-			ld.Errorf(s, "%s+%v is not 2-byte aligned", r.Sym.Name, r.Sym.Value)
+		if t&1 != 0 {
+			ldr.Errorf(s, "%s+%v is not 2-byte aligned", ldr.SymName(r.Sym()), ldr.SymValue(r.Sym()))
 		}
 		return t >> 1
 	}
 }
 
-func addpltsym2(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym) {
+func addpltsym(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym) {
 	if ldr.SymPlt(s) >= 0 {
 		return
 	}
 
-	ld.Adddynsym2(ldr, target, syms, s)
+	ld.Adddynsym(ldr, target, syms, s)
 
 	if target.IsElf() {
-		plt := ldr.MakeSymbolUpdater(syms.PLT2)
-		got := ldr.MakeSymbolUpdater(syms.GOT2)
-		rela := ldr.MakeSymbolUpdater(syms.RelaPLT2)
+		plt := ldr.MakeSymbolUpdater(syms.PLT)
+		got := ldr.MakeSymbolUpdater(syms.GOT)
+		rela := ldr.MakeSymbolUpdater(syms.RelaPLT)
 		if plt.Size() == 0 {
 			panic("plt is not set up")
 		}
@@ -464,92 +454,3 @@
 		ldr.Errorf(s, "addpltsym: unsupported binary format")
 	}
 }
-
-func addgotsym2(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym) {
-	if ldr.SymGot(s) >= 0 {
-		return
-	}
-
-	ld.Adddynsym2(ldr, target, syms, s)
-	got := ldr.MakeSymbolUpdater(syms.GOT2)
-	ldr.SetGot(s, int32(got.Size()))
-	got.AddUint64(target.Arch, 0)
-
-	if target.IsElf() {
-		rela := ldr.MakeSymbolUpdater(syms.Rela2)
-		rela.AddAddrPlus(target.Arch, got.Sym(), int64(ldr.SymGot(s)))
-		rela.AddUint64(target.Arch, ld.ELF64_R_INFO(uint32(ldr.SymDynid(s)), uint32(elf.R_390_GLOB_DAT)))
-		rela.AddUint64(target.Arch, 0)
-	} else {
-		ldr.Errorf(s, "addgotsym: unsupported binary format")
-	}
-}
-
-func asmb(ctxt *ld.Link, _ *loader.Loader) {
-	if ctxt.IsELF {
-		ld.Asmbelfsetup()
-	}
-
-	var wg sync.WaitGroup
-	sect := ld.Segtext.Sections[0]
-	offset := sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff
-	ld.WriteParallel(&wg, ld.Codeblk, ctxt, offset, sect.Vaddr, sect.Length)
-
-	for _, sect := range ld.Segtext.Sections[1:] {
-		offset := sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff
-		ld.WriteParallel(&wg, ld.Datblk, ctxt, offset, sect.Vaddr, sect.Length)
-	}
-
-	if ld.Segrodata.Filelen > 0 {
-		ld.WriteParallel(&wg, ld.Datblk, ctxt, ld.Segrodata.Fileoff, ld.Segrodata.Vaddr, ld.Segrodata.Filelen)
-	}
-
-	if ld.Segrelrodata.Filelen > 0 {
-		ld.WriteParallel(&wg, ld.Datblk, ctxt, ld.Segrelrodata.Fileoff, ld.Segrelrodata.Vaddr, ld.Segrelrodata.Filelen)
-	}
-
-	ld.WriteParallel(&wg, ld.Datblk, ctxt, ld.Segdata.Fileoff, ld.Segdata.Vaddr, ld.Segdata.Filelen)
-
-	ld.WriteParallel(&wg, ld.Dwarfblk, ctxt, ld.Segdwarf.Fileoff, ld.Segdwarf.Vaddr, ld.Segdwarf.Filelen)
-	wg.Wait()
-}
-
-func asmb2(ctxt *ld.Link) {
-	/* output symbol table */
-	ld.Symsize = 0
-
-	ld.Lcsize = 0
-	symo := uint32(0)
-	if !*ld.FlagS {
-		if !ctxt.IsELF {
-			ld.Errorf(nil, "unsupported executable format")
-		}
-		symo = uint32(ld.Segdwarf.Fileoff + ld.Segdwarf.Filelen)
-		symo = uint32(ld.Rnd(int64(symo), int64(*ld.FlagRound)))
-
-		ctxt.Out.SeekSet(int64(symo))
-		ld.Asmelfsym(ctxt)
-		ctxt.Out.Write(ld.Elfstrdat)
-
-		if ctxt.LinkMode == ld.LinkExternal {
-			ld.Elfemitreloc(ctxt)
-		}
-	}
-
-	ctxt.Out.SeekSet(0)
-	switch ctxt.HeadType {
-	default:
-		ld.Errorf(nil, "unsupported operating system")
-	case objabi.Hlinux:
-		ld.Asmbelf(ctxt, int64(symo))
-	}
-
-	if *ld.FlagC {
-		fmt.Printf("textsize=%d\n", ld.Segtext.Filelen)
-		fmt.Printf("datsize=%d\n", ld.Segdata.Filelen)
-		fmt.Printf("bsssize=%d\n", ld.Segdata.Length-ld.Segdata.Filelen)
-		fmt.Printf("symsize=%d\n", ld.Symsize)
-		fmt.Printf("lcsize=%d\n", ld.Lcsize)
-		fmt.Printf("total=%d\n", ld.Segtext.Filelen+ld.Segdata.Length+uint64(ld.Symsize)+uint64(ld.Lcsize))
-	}
-}
diff --git a/src/cmd/link/internal/s390x/obj.go b/src/cmd/link/internal/s390x/obj.go
index d4ac5af..bb62fe1 100644
--- a/src/cmd/link/internal/s390x/obj.go
+++ b/src/cmd/link/internal/s390x/obj.go
@@ -46,15 +46,13 @@
 		Dwarfregsp: dwarfRegSP,
 		Dwarfreglr: dwarfRegLR,
 
-		Adddynrel2:       adddynrel2,
+		Adddynrel:        adddynrel,
 		Archinit:         archinit,
 		Archreloc:        archreloc,
 		Archrelocvariant: archrelocvariant,
-		Asmb:             asmb,  // in asm.go
-		Asmb2:            asmb2, // in asm.go
 		Elfreloc1:        elfreloc1,
 		Elfsetupplt:      elfsetupplt,
-		Gentext2:         gentext2,
+		Gentext:          gentext,
 		Machoreloc1:      machoreloc1,
 
 		Linuxdynld: "/lib64/ld64.so.1",
diff --git a/src/cmd/link/internal/sym/attribute.go b/src/cmd/link/internal/sym/attribute.go
deleted file mode 100644
index eda3fe6..0000000
--- a/src/cmd/link/internal/sym/attribute.go
+++ /dev/null
@@ -1,129 +0,0 @@
-// Copyright 2017 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 sym
-
-import "sync/atomic"
-
-// Attribute is a set of common symbol attributes.
-type Attribute int32
-
-const (
-	// AttrDuplicateOK marks a symbol that can be present in multiple object
-	// files.
-	AttrDuplicateOK Attribute = 1 << iota
-	// AttrExternal marks function symbols loaded from host object files.
-	AttrExternal
-	// AttrNoSplit marks functions that cannot split the stack; the linker
-	// cares because it checks that there are no call chains of nosplit
-	// functions that require more than StackLimit bytes (see
-	// lib.go:dostkcheck)
-	AttrNoSplit
-	// AttrReachable marks symbols that are transitively referenced from the
-	// entry points. Unreachable symbols are not written to the output.
-	AttrReachable
-	// AttrCgoExportDynamic and AttrCgoExportStatic mark symbols referenced
-	// by directives written by cgo (in response to //export directives in
-	// the source).
-	AttrCgoExportDynamic
-	AttrCgoExportStatic
-	// AttrSpecial marks symbols that do not have their address (i.e. Value)
-	// computed by the usual mechanism of data.go:dodata() &
-	// data.go:address().
-	AttrSpecial
-	// AttrStackCheck is used by dostkcheck to only check each NoSplit
-	// function's stack usage once.
-	AttrStackCheck
-	// AttrNotInSymbolTable marks symbols that are not written to the symbol table.
-	AttrNotInSymbolTable
-	// AttrOnList marks symbols that are on some list (such as the list of
-	// all text symbols, or one of the lists of data symbols) and is
-	// consulted to avoid bugs where a symbol is put on a list twice.
-	AttrOnList
-	// AttrLocal marks symbols that are only visible within the module
-	// (executable or shared library) being linked. Only relevant when
-	// dynamically linking Go code.
-	AttrLocal
-	// AttrReflectMethod marks certain methods from the reflect package that
-	// can be used to call arbitrary methods. If no symbol with this bit set
-	// is marked as reachable, more dead code elimination can be done.
-	AttrReflectMethod
-	// AttrMakeTypelink Amarks types that should be added to the typelink
-	// table. See typelinks.go:typelinks().
-	AttrMakeTypelink
-	// AttrShared marks symbols compiled with the -shared option.
-	AttrShared
-	// AttrVisibilityHidden symbols are ELF symbols with
-	// visibility set to STV_HIDDEN. They become local symbols in
-	// the final executable. Only relevant when internally linking
-	// on an ELF platform.
-	AttrVisibilityHidden
-	// AttrSubSymbol mostly means that the symbol appears on the Sub list of some
-	// other symbol.  Unfortunately, it's not 100% reliable; at least, it's not set
-	// correctly for the .TOC. symbol in Link.dodata.  Usually the Outer field of the
-	// symbol points to the symbol whose list it is on, but that it is not set for the
-	// symbols added to .windynamic in initdynimport in pe.go.
-	//
-	// TODO(mwhudson): fix the inconsistencies noticed above.
-	//
-	// Sub lists are used when loading host objects (sections from the host object
-	// become regular linker symbols and symbols go on the Sub list of their section)
-	// and for constructing the global offset table when internally linking a dynamic
-	// executable.
-	//
-	// TODO(mwhudson): perhaps a better name for this is AttrNonGoSymbol.
-	AttrSubSymbol
-	// AttrContainer is set on text symbols that are present as the .Outer for some
-	// other symbol.
-	AttrContainer
-	// AttrTopFrame means that the function is an entry point and unwinders
-	// should stop when they hit this function.
-	AttrTopFrame
-	// AttrReadOnly indicates whether the symbol's content (Symbol.P) is backed by
-	// read-only memory.
-	AttrReadOnly
-	// 19 attributes defined so far.
-)
-
-func (a *Attribute) load() Attribute { return Attribute(atomic.LoadInt32((*int32)(a))) }
-
-func (a *Attribute) DuplicateOK() bool      { return a.load()&AttrDuplicateOK != 0 }
-func (a *Attribute) External() bool         { return a.load()&AttrExternal != 0 }
-func (a *Attribute) NoSplit() bool          { return a.load()&AttrNoSplit != 0 }
-func (a *Attribute) Reachable() bool        { return a.load()&AttrReachable != 0 }
-func (a *Attribute) CgoExportDynamic() bool { return a.load()&AttrCgoExportDynamic != 0 }
-func (a *Attribute) CgoExportStatic() bool  { return a.load()&AttrCgoExportStatic != 0 }
-func (a *Attribute) Special() bool          { return a.load()&AttrSpecial != 0 }
-func (a *Attribute) StackCheck() bool       { return a.load()&AttrStackCheck != 0 }
-func (a *Attribute) NotInSymbolTable() bool { return a.load()&AttrNotInSymbolTable != 0 }
-func (a *Attribute) OnList() bool           { return a.load()&AttrOnList != 0 }
-func (a *Attribute) Local() bool            { return a.load()&AttrLocal != 0 }
-func (a *Attribute) ReflectMethod() bool    { return a.load()&AttrReflectMethod != 0 }
-func (a *Attribute) MakeTypelink() bool     { return a.load()&AttrMakeTypelink != 0 }
-func (a *Attribute) Shared() bool           { return a.load()&AttrShared != 0 }
-func (a *Attribute) VisibilityHidden() bool { return a.load()&AttrVisibilityHidden != 0 }
-func (a *Attribute) SubSymbol() bool        { return a.load()&AttrSubSymbol != 0 }
-func (a *Attribute) Container() bool        { return a.load()&AttrContainer != 0 }
-func (a *Attribute) TopFrame() bool         { return a.load()&AttrTopFrame != 0 }
-func (a *Attribute) ReadOnly() bool         { return a.load()&AttrReadOnly != 0 }
-
-func (a *Attribute) CgoExport() bool {
-	return a.CgoExportDynamic() || a.CgoExportStatic()
-}
-
-func (a *Attribute) Set(flag Attribute, value bool) {
-	// XXX it would be nice if we have atomic And, Or.
-	for {
-		a0 := a.load()
-		var anew Attribute
-		if value {
-			anew = a0 | flag
-		} else {
-			anew = a0 &^ flag
-		}
-		if atomic.CompareAndSwapInt32((*int32)(a), int32(a0), int32(anew)) {
-			return
-		}
-	}
-}
diff --git a/src/cmd/link/internal/sym/compilation_unit.go b/src/cmd/link/internal/sym/compilation_unit.go
index b8b6845..d9bfc84 100644
--- a/src/cmd/link/internal/sym/compilation_unit.go
+++ b/src/cmd/link/internal/sym/compilation_unit.go
@@ -16,18 +16,13 @@
 type CompilationUnit struct {
 	Pkg            string        // The package name, eg ("fmt", or "runtime")
 	Lib            *Library      // Our library
-	Consts         *Symbol       // Package constants DIEs
 	PCs            []dwarf.Range // PC ranges, relative to Textp[0]
 	DWInfo         *dwarf.DWDie  // CU root DIE
-	FuncDIEs       []*Symbol     // Function DIE subtrees
-	AbsFnDIEs      []*Symbol     // Abstract function DIE subtrees
-	RangeSyms      []*Symbol     // Symbols for debug_range
-	Textp          []*Symbol     // Text symbols in this CU
 	DWARFFileTable []string      // The file table used to generate the .debug_lines
 
-	Consts2    LoaderSym   // Package constants DIEs (loader)
-	FuncDIEs2  []LoaderSym // Function DIE subtrees (loader)
-	AbsFnDIEs2 []LoaderSym // Abstract function DIE subtrees (loader)
-	RangeSyms2 []LoaderSym // Symbols for debug_range (loader)
-	Textp2     []LoaderSym // Text symbols in this CU (loader)
+	Consts    LoaderSym   // Package constants DIEs
+	FuncDIEs  []LoaderSym // Function DIE subtrees
+	AbsFnDIEs []LoaderSym // Abstract function DIE subtrees
+	RangeSyms []LoaderSym // Symbols for debug_range
+	Textp     []LoaderSym // Text symbols in this CU
 }
diff --git a/src/cmd/link/internal/sym/library.go b/src/cmd/link/internal/sym/library.go
index c9be3ab..7f6e63c 100644
--- a/src/cmd/link/internal/sym/library.go
+++ b/src/cmd/link/internal/sym/library.go
@@ -12,16 +12,14 @@
 	File        string
 	Pkg         string
 	Shlib       string
-	Hash        string
 	Fingerprint goobj2.FingerprintType
 	Autolib     []goobj2.ImportedPkg
 	Imports     []*Library
 	Main        bool
-	Safe        bool
 	Units       []*CompilationUnit
 
-	Textp2       []LoaderSym // text syms defined in this library
-	DupTextSyms2 []LoaderSym // dupok text syms defined in this library
+	Textp       []LoaderSym // text syms defined in this library
+	DupTextSyms []LoaderSym // dupok text syms defined in this library
 }
 
 func (l Library) String() string {
diff --git a/src/cmd/link/internal/sym/reloc.go b/src/cmd/link/internal/sym/reloc.go
index f589447..a543233 100644
--- a/src/cmd/link/internal/sym/reloc.go
+++ b/src/cmd/link/internal/sym/reloc.go
@@ -10,41 +10,6 @@
 	"debug/elf"
 )
 
-// Reloc is a relocation.
-//
-// The typical Reloc rewrites part of a symbol at offset Off to address Sym.
-// A Reloc is stored in a slice on the Symbol it rewrites.
-//
-// Relocations are generated by the compiler as the type
-// cmd/internal/obj.Reloc, which is encoded into the object file wire
-// format and decoded by the linker into this type. A separate type is
-// used to hold linker-specific state about the relocation.
-//
-// Some relocations are created by cmd/link.
-type Reloc struct {
-	Off       int32            // offset to rewrite
-	Siz       uint8            // number of bytes to rewrite, 1, 2, or 4
-	Done      bool             // set to true when relocation is complete
-	Type      objabi.RelocType // the relocation type
-	Add       int64            // addend
-	Sym       *Symbol          // symbol the relocation addresses
-	*RelocExt                  // extra fields (see below), may be nil, call InitExt before use
-}
-
-// relocExt contains extra fields in Reloc that are used only in
-// certain cases.
-type RelocExt struct {
-	Xadd    int64        // addend passed to external linker
-	Xsym    *Symbol      // symbol passed to external linker
-	Variant RelocVariant // variation on Type, currently used only on PPC64 and S390X
-}
-
-func (r *Reloc) InitExt() {
-	if r.RelocExt == nil {
-		r.RelocExt = new(RelocExt)
-	}
-}
-
 // RelocVariant is a linker-internal variation on a relocation.
 type RelocVariant uint8
 
@@ -107,22 +72,3 @@
 
 	return r.String()
 }
-
-// RelocByOff implements sort.Interface for sorting relocations by offset.
-type RelocByOff []Reloc
-
-func (x RelocByOff) Len() int { return len(x) }
-
-func (x RelocByOff) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
-
-func (x RelocByOff) Less(i, j int) bool {
-	a := &x[i]
-	b := &x[j]
-	if a.Off < b.Off {
-		return true
-	}
-	if a.Off > b.Off {
-		return false
-	}
-	return false
-}
diff --git a/src/cmd/link/internal/sym/segment.go b/src/cmd/link/internal/sym/segment.go
index 5aa0bc5..9b49c62 100644
--- a/src/cmd/link/internal/sym/segment.go
+++ b/src/cmd/link/internal/sym/segment.go
@@ -55,7 +55,6 @@
 	Elfsect interface{} // an *ld.ElfShdr
 	Reloff  uint64
 	Rellen  uint64
-	Sym     *Symbol   // symbol for the section, if any
-	Sym2    LoaderSym // symbol for the section, if any
+	Sym     LoaderSym // symbol for the section, if any
 	Index   uint16    // each section has a unique index, used internally
 }
diff --git a/src/cmd/link/internal/sym/sizeof_test.go b/src/cmd/link/internal/sym/sizeof_test.go
deleted file mode 100644
index f358cce..0000000
--- a/src/cmd/link/internal/sym/sizeof_test.go
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright 2018 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 sym
-
-import (
-	"reflect"
-	"testing"
-	"unsafe"
-)
-
-// Assert that the size of important structures do not change unexpectedly.
-
-func TestSizeof(t *testing.T) {
-	const nbit = unsafe.Sizeof(uintptr(0)) * 8
-	const _64bit = nbit == 64
-
-	var tests = []struct {
-		val    interface{} // type as a value
-		_32bit uintptr     // size on 32bit platforms
-		_64bit uintptr     // size on 64bit platforms
-	}{
-		{Symbol{}, 80, 128},
-	}
-
-	for _, tt := range tests {
-		want := tt._32bit
-		if _64bit {
-			want = tt._64bit
-		}
-		got := reflect.TypeOf(tt.val).Size()
-		if want != got {
-			t.Errorf("%d bit unsafe.Sizeof(%T) = %d, want %d", nbit, tt.val, got, want)
-		}
-	}
-}
diff --git a/src/cmd/link/internal/sym/symbol.go b/src/cmd/link/internal/sym/symbol.go
index 3c3717f..1a4165e 100644
--- a/src/cmd/link/internal/sym/symbol.go
+++ b/src/cmd/link/internal/sym/symbol.go
@@ -6,46 +6,8 @@
 
 import (
 	"cmd/internal/obj"
-	"cmd/internal/objabi"
-	"cmd/internal/sys"
-	"debug/elf"
-	"fmt"
-	"log"
 )
 
-// Symbol is an entry in the symbol table.
-type Symbol struct {
-	Name    string
-	Type    SymKind
-	Version int16
-	Attr    Attribute
-	Dynid   int32
-	Align   int32
-	Value   int64
-	Size    int64
-	Outer   *Symbol
-	SymIdx  LoaderSym
-	auxinfo *AuxSymbol
-	Sect    *Section
-	// P contains the raw symbol data.
-	P []byte
-	R []Reloc
-}
-
-// AuxSymbol contains less-frequently used sym.Symbol fields.
-type AuxSymbol struct {
-	extname    string
-	dynimplib  string
-	dynimpvers string
-	localentry uint8
-	plt        int32
-	got        int32
-	// ElfType is set for symbols read from shared libraries by ldshlibsyms. It
-	// is not set for symbols defined by the packages being linked or by symbols
-	// read by ldelf (and so is left as elf.STT_NOTYPE).
-	elftype elf.SymType
-}
-
 const (
 	SymVerABI0        = 0
 	SymVerABIInternal = 1
@@ -72,363 +34,6 @@
 	return ^obj.ABI(0), false
 }
 
-func (s *Symbol) String() string {
-	if s.Version == 0 {
-		return s.Name
-	}
-	return fmt.Sprintf("%s<%d>", s.Name, s.Version)
-}
-
-func (s *Symbol) IsFileLocal() bool {
-	return s.Version >= SymVerStatic
-}
-
-func (s *Symbol) Len() int64 {
-	return s.Size
-}
-
-func (s *Symbol) Length(dwarfContext interface{}) int64 {
-	return s.Size
-}
-
-func (s *Symbol) Grow(siz int64) {
-	if int64(int(siz)) != siz {
-		log.Fatalf("symgrow size %d too long", siz)
-	}
-	if int64(len(s.P)) >= siz {
-		return
-	}
-	if cap(s.P) < int(siz) {
-		p := make([]byte, 2*(siz+1))
-		s.P = append(p[:0], s.P...)
-	}
-	s.P = s.P[:siz]
-}
-
-func (s *Symbol) AddBytes(bytes []byte) int64 {
-	if s.Type == 0 {
-		s.Type = SDATA
-	}
-	s.Attr |= AttrReachable
-	s.P = append(s.P, bytes...)
-	s.Size = int64(len(s.P))
-
-	return s.Size
-}
-
-func (s *Symbol) AddUint8(v uint8) int64 {
-	off := s.Size
-	if s.Type == 0 {
-		s.Type = SDATA
-	}
-	s.Attr |= AttrReachable
-	s.Size++
-	s.P = append(s.P, v)
-
-	return off
-}
-
-func (s *Symbol) AddUint16(arch *sys.Arch, v uint16) int64 {
-	return s.AddUintXX(arch, uint64(v), 2)
-}
-
-func (s *Symbol) AddUint32(arch *sys.Arch, v uint32) int64 {
-	return s.AddUintXX(arch, uint64(v), 4)
-}
-
-func (s *Symbol) AddUint64(arch *sys.Arch, v uint64) int64 {
-	return s.AddUintXX(arch, v, 8)
-}
-
-func (s *Symbol) AddUint(arch *sys.Arch, v uint64) int64 {
-	return s.AddUintXX(arch, v, arch.PtrSize)
-}
-
-func (s *Symbol) SetUint8(arch *sys.Arch, r int64, v uint8) int64 {
-	return s.setUintXX(arch, r, uint64(v), 1)
-}
-
-func (s *Symbol) SetUint16(arch *sys.Arch, r int64, v uint16) int64 {
-	return s.setUintXX(arch, r, uint64(v), 2)
-}
-
-func (s *Symbol) SetUint32(arch *sys.Arch, r int64, v uint32) int64 {
-	return s.setUintXX(arch, r, uint64(v), 4)
-}
-
-func (s *Symbol) SetUint(arch *sys.Arch, r int64, v uint64) int64 {
-	return s.setUintXX(arch, r, v, int64(arch.PtrSize))
-}
-
-func (s *Symbol) addAddrPlus(arch *sys.Arch, t *Symbol, add int64, typ objabi.RelocType) int64 {
-	if s.Type == 0 {
-		s.Type = SDATA
-	}
-	s.Attr |= AttrReachable
-	i := s.Size
-	s.Size += int64(arch.PtrSize)
-	s.Grow(s.Size)
-	r := s.AddRel()
-	r.Sym = t
-	r.Off = int32(i)
-	r.Siz = uint8(arch.PtrSize)
-	r.Type = typ
-	r.Add = add
-	return i + int64(r.Siz)
-}
-
-func (s *Symbol) AddAddrPlus(arch *sys.Arch, t *Symbol, add int64) int64 {
-	return s.addAddrPlus(arch, t, add, objabi.R_ADDR)
-}
-
-func (s *Symbol) AddCURelativeAddrPlus(arch *sys.Arch, t *Symbol, add int64) int64 {
-	return s.addAddrPlus(arch, t, add, objabi.R_ADDRCUOFF)
-}
-
-func (s *Symbol) AddPCRelPlus(arch *sys.Arch, t *Symbol, add int64) int64 {
-	if s.Type == 0 {
-		s.Type = SDATA
-	}
-	s.Attr |= AttrReachable
-	i := s.Size
-	s.Size += 4
-	s.Grow(s.Size)
-	r := s.AddRel()
-	r.Sym = t
-	r.Off = int32(i)
-	r.Add = add
-	r.Type = objabi.R_PCREL
-	r.Siz = 4
-	if arch.Family == sys.S390X || arch.Family == sys.PPC64 {
-		r.InitExt()
-	}
-	if arch.Family == sys.S390X {
-		r.Variant = RV_390_DBL
-	}
-	return i + int64(r.Siz)
-}
-
-func (s *Symbol) AddAddr(arch *sys.Arch, t *Symbol) int64 {
-	return s.AddAddrPlus(arch, t, 0)
-}
-
-func (s *Symbol) SetAddrPlus(arch *sys.Arch, off int64, t *Symbol, add int64) int64 {
-	if s.Type == 0 {
-		s.Type = SDATA
-	}
-	s.Attr |= AttrReachable
-	if off+int64(arch.PtrSize) > s.Size {
-		s.Size = off + int64(arch.PtrSize)
-		s.Grow(s.Size)
-	}
-
-	r := s.AddRel()
-	r.Sym = t
-	r.Off = int32(off)
-	r.Siz = uint8(arch.PtrSize)
-	r.Type = objabi.R_ADDR
-	r.Add = add
-	return off + int64(r.Siz)
-}
-
-func (s *Symbol) SetAddr(arch *sys.Arch, off int64, t *Symbol) int64 {
-	return s.SetAddrPlus(arch, off, t, 0)
-}
-
-func (s *Symbol) AddSize(arch *sys.Arch, t *Symbol) int64 {
-	if s.Type == 0 {
-		s.Type = SDATA
-	}
-	s.Attr |= AttrReachable
-	i := s.Size
-	s.Size += int64(arch.PtrSize)
-	s.Grow(s.Size)
-	r := s.AddRel()
-	r.Sym = t
-	r.Off = int32(i)
-	r.Siz = uint8(arch.PtrSize)
-	r.Type = objabi.R_SIZE
-	return i + int64(r.Siz)
-}
-
-func (s *Symbol) AddAddrPlus4(t *Symbol, add int64) int64 {
-	if s.Type == 0 {
-		s.Type = SDATA
-	}
-	s.Attr |= AttrReachable
-	i := s.Size
-	s.Size += 4
-	s.Grow(s.Size)
-	r := s.AddRel()
-	r.Sym = t
-	r.Off = int32(i)
-	r.Siz = 4
-	r.Type = objabi.R_ADDR
-	r.Add = add
-	return i + int64(r.Siz)
-}
-
-func (s *Symbol) AddRel() *Reloc {
-	s.R = append(s.R, Reloc{})
-	return &s.R[len(s.R)-1]
-}
-
-func (s *Symbol) AddUintXX(arch *sys.Arch, v uint64, wid int) int64 {
-	off := s.Size
-	s.setUintXX(arch, off, v, int64(wid))
-	return off
-}
-
-func (s *Symbol) setUintXX(arch *sys.Arch, off int64, v uint64, wid int64) int64 {
-	if s.Type == 0 {
-		s.Type = SDATA
-	}
-	s.Attr |= AttrReachable
-	if s.Size < off+wid {
-		s.Size = off + wid
-		s.Grow(s.Size)
-	}
-
-	switch wid {
-	case 1:
-		s.P[off] = uint8(v)
-	case 2:
-		arch.ByteOrder.PutUint16(s.P[off:], uint16(v))
-	case 4:
-		arch.ByteOrder.PutUint32(s.P[off:], uint32(v))
-	case 8:
-		arch.ByteOrder.PutUint64(s.P[off:], v)
-	}
-
-	return off + wid
-}
-
-func (s *Symbol) makeAuxInfo() {
-	if s.auxinfo == nil {
-		s.auxinfo = &AuxSymbol{extname: s.Name, plt: -1, got: -1}
-	}
-}
-
-func (s *Symbol) Extname() string {
-	if s.auxinfo == nil {
-		return s.Name
-	}
-	return s.auxinfo.extname
-}
-
-func (s *Symbol) SetExtname(n string) {
-	if s.auxinfo == nil {
-		if s.Name == n {
-			return
-		}
-		s.makeAuxInfo()
-	}
-	s.auxinfo.extname = n
-}
-
-func (s *Symbol) Dynimplib() string {
-	if s.auxinfo == nil {
-		return ""
-	}
-	return s.auxinfo.dynimplib
-}
-
-func (s *Symbol) Dynimpvers() string {
-	if s.auxinfo == nil {
-		return ""
-	}
-	return s.auxinfo.dynimpvers
-}
-
-func (s *Symbol) SetDynimplib(lib string) {
-	if s.auxinfo == nil {
-		s.makeAuxInfo()
-	}
-	s.auxinfo.dynimplib = lib
-}
-
-func (s *Symbol) SetDynimpvers(vers string) {
-	if s.auxinfo == nil {
-		s.makeAuxInfo()
-	}
-	s.auxinfo.dynimpvers = vers
-}
-
-func (s *Symbol) ResetDyninfo() {
-	if s.auxinfo != nil {
-		s.auxinfo.dynimplib = ""
-		s.auxinfo.dynimpvers = ""
-	}
-}
-
-func (s *Symbol) Localentry() uint8 {
-	if s.auxinfo == nil {
-		return 0
-	}
-	return s.auxinfo.localentry
-}
-
-func (s *Symbol) SetLocalentry(val uint8) {
-	if s.auxinfo == nil {
-		if val != 0 {
-			return
-		}
-		s.makeAuxInfo()
-	}
-	s.auxinfo.localentry = val
-}
-
-func (s *Symbol) Plt() int32 {
-	if s.auxinfo == nil {
-		return -1
-	}
-	return s.auxinfo.plt
-}
-
-func (s *Symbol) SetPlt(val int32) {
-	if s.auxinfo == nil {
-		if val == -1 {
-			return
-		}
-		s.makeAuxInfo()
-	}
-	s.auxinfo.plt = val
-}
-
-func (s *Symbol) Got() int32 {
-	if s.auxinfo == nil {
-		return -1
-	}
-	return s.auxinfo.got
-}
-
-func (s *Symbol) SetGot(val int32) {
-	if s.auxinfo == nil {
-		if val == -1 {
-			return
-		}
-		s.makeAuxInfo()
-	}
-	s.auxinfo.got = val
-}
-
-func (s *Symbol) ElfType() elf.SymType {
-	if s.auxinfo == nil {
-		return elf.STT_NOTYPE
-	}
-	return s.auxinfo.elftype
-}
-
-func (s *Symbol) SetElfType(val elf.SymType) {
-	if s.auxinfo == nil {
-		if val == elf.STT_NOTYPE {
-			return
-		}
-		s.makeAuxInfo()
-	}
-	s.auxinfo.elftype = val
-}
-
 type Pcdata struct {
 	P []byte
 }
diff --git a/src/cmd/link/internal/sym/symbols.go b/src/cmd/link/internal/sym/symbols.go
deleted file mode 100644
index 721828d..0000000
--- a/src/cmd/link/internal/sym/symbols.go
+++ /dev/null
@@ -1,63 +0,0 @@
-// Derived from Inferno utils/6l/l.h and related files.
-// https://bitbucket.org/inferno-os/inferno-os/src/master/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 sym
-
-type Symbols struct {
-	// Symbol lookup based on name and indexed by version.
-	versions int
-
-	// Provided by the loader
-
-	// Look up the symbol with the given name and version, creating the
-	// symbol if it is not found.
-	Lookup func(name string, v int) *Symbol
-
-	// Look up the symbol with the given name and version, returning nil
-	// if it is not found.
-	ROLookup func(name string, v int) *Symbol
-}
-
-func NewSymbols() *Symbols {
-	return &Symbols{
-		versions: SymVerStatic,
-	}
-}
-
-// Allocate a new version (i.e. symbol namespace).
-func (syms *Symbols) IncVersion() int {
-	syms.versions++
-	return syms.versions - 1
-}
-
-// returns the maximum version number
-func (syms *Symbols) MaxVersion() int {
-	return syms.versions
-}
diff --git a/src/cmd/link/internal/sym/symkind.go b/src/cmd/link/internal/sym/symkind.go
index 3a1cad9..3e47d9a 100644
--- a/src/cmd/link/internal/sym/symkind.go
+++ b/src/cmd/link/internal/sym/symkind.go
@@ -102,14 +102,19 @@
 	SMACHOINDIRECTPLT
 	SMACHOINDIRECTGOT
 	SFILEPATH
-	SCONST
 	SDYNIMPORT
 	SHOSTOBJ
 	SUNDEFEXT // Undefined symbol for resolution by external linker
 
 	// Sections for debugging information
 	SDWARFSECT
-	SDWARFINFO
+	// DWARF symbol types
+	SDWARFCUINFO
+	SDWARFCONST
+	SDWARFFCN
+	SDWARFABSFCN
+	SDWARFTYPE
+	SDWARFVAR
 	SDWARFRANGE
 	SDWARFLOC
 	SDWARFLINES
@@ -129,7 +134,12 @@
 	SBSS,
 	SNOPTRBSS,
 	STLSBSS,
-	SDWARFINFO,
+	SDWARFCUINFO,
+	SDWARFCONST,
+	SDWARFFCN,
+	SDWARFABSFCN,
+	SDWARFTYPE,
+	SDWARFVAR,
 	SDWARFRANGE,
 	SDWARFLOC,
 	SDWARFLINES,
diff --git a/src/cmd/link/internal/sym/symkind_string.go b/src/cmd/link/internal/sym/symkind_string.go
index 97af992..47b2406 100644
--- a/src/cmd/link/internal/sym/symkind_string.go
+++ b/src/cmd/link/internal/sym/symkind_string.go
@@ -1,4 +1,4 @@
-// Code generated by "stringer -type=SymKind symkind.go"; DO NOT EDIT.
+// Code generated by "stringer -type=SymKindstringer -type=SymKind"; DO NOT EDIT.
 
 package sym
 
@@ -52,21 +52,25 @@
 	_ = x[SMACHOINDIRECTPLT-41]
 	_ = x[SMACHOINDIRECTGOT-42]
 	_ = x[SFILEPATH-43]
-	_ = x[SCONST-44]
-	_ = x[SDYNIMPORT-45]
-	_ = x[SHOSTOBJ-46]
-	_ = x[SUNDEFEXT-47]
-	_ = x[SDWARFSECT-48]
-	_ = x[SDWARFINFO-49]
-	_ = x[SDWARFRANGE-50]
-	_ = x[SDWARFLOC-51]
-	_ = x[SDWARFLINES-52]
-	_ = x[SABIALIAS-53]
+	_ = x[SDYNIMPORT-44]
+	_ = x[SHOSTOBJ-45]
+	_ = x[SUNDEFEXT-46]
+	_ = x[SDWARFSECT-47]
+	_ = x[SDWARFCUINFO-48]
+	_ = x[SDWARFCONST-49]
+	_ = x[SDWARFFCN-50]
+	_ = x[SDWARFABSFCN-51]
+	_ = x[SDWARFTYPE-52]
+	_ = x[SDWARFVAR-53]
+	_ = x[SDWARFRANGE-54]
+	_ = x[SDWARFLOC-55]
+	_ = x[SDWARFLINES-56]
+	_ = x[SABIALIAS-57]
 }
 
-const _SymKind_name = "SxxxSTEXTSELFRXSECTSTYPESSTRINGSGOSTRINGSGOFUNCSGCBITSSRODATASFUNCTABSELFROSECTSMACHOPLTSTYPERELROSSTRINGRELROSGOSTRINGRELROSGOFUNCRELROSGCBITSRELROSRODATARELROSFUNCTABRELROSTYPELINKSITABLINKSSYMTABSPCLNTABSFirstWritableSBUILDINFOSELFSECTSMACHOSMACHOGOTSWINDOWSSELFGOTSNOPTRDATASINITARRSDATASXCOFFTOCSBSSSNOPTRBSSSLIBFUZZER_EXTRA_COUNTERSTLSBSSSXREFSMACHOSYMSTRSMACHOSYMTABSMACHOINDIRECTPLTSMACHOINDIRECTGOTSFILEPATHSCONSTSDYNIMPORTSHOSTOBJSUNDEFEXTSDWARFSECTSDWARFINFOSDWARFRANGESDWARFLOCSDWARFLINESSABIALIAS"
+const _SymKind_name = "SxxxSTEXTSELFRXSECTSTYPESSTRINGSGOSTRINGSGOFUNCSGCBITSSRODATASFUNCTABSELFROSECTSMACHOPLTSTYPERELROSSTRINGRELROSGOSTRINGRELROSGOFUNCRELROSGCBITSRELROSRODATARELROSFUNCTABRELROSTYPELINKSITABLINKSSYMTABSPCLNTABSFirstWritableSBUILDINFOSELFSECTSMACHOSMACHOGOTSWINDOWSSELFGOTSNOPTRDATASINITARRSDATASXCOFFTOCSBSSSNOPTRBSSSLIBFUZZER_EXTRA_COUNTERSTLSBSSSXREFSMACHOSYMSTRSMACHOSYMTABSMACHOINDIRECTPLTSMACHOINDIRECTGOTSFILEPATHSDYNIMPORTSHOSTOBJSUNDEFEXTSDWARFSECTSDWARFCUINFOSDWARFCONSTSDWARFFCNSDWARFABSFCNSDWARFTYPESDWARFVARSDWARFRANGESDWARFLOCSDWARFLINESSABIALIAS"
 
-var _SymKind_index = [...]uint16{0, 4, 9, 19, 24, 31, 40, 47, 54, 61, 69, 79, 88, 98, 110, 124, 136, 148, 160, 173, 182, 191, 198, 206, 220, 230, 238, 244, 253, 261, 268, 278, 286, 291, 300, 304, 313, 337, 344, 349, 361, 373, 390, 407, 416, 422, 432, 440, 449, 459, 469, 480, 489, 500, 509}
+var _SymKind_index = [...]uint16{0, 4, 9, 19, 24, 31, 40, 47, 54, 61, 69, 79, 88, 98, 110, 124, 136, 148, 160, 173, 182, 191, 198, 206, 220, 230, 238, 244, 253, 261, 268, 278, 286, 291, 300, 304, 313, 337, 344, 349, 361, 373, 390, 407, 416, 426, 434, 443, 453, 465, 476, 485, 497, 507, 516, 527, 536, 547, 556}
 
 func (i SymKind) String() string {
 	if i >= SymKind(len(_SymKind_index)-1) {
diff --git a/src/cmd/link/internal/wasm/asm.go b/src/cmd/link/internal/wasm/asm.go
index 1eb3291..2be4adc 100644
--- a/src/cmd/link/internal/wasm/asm.go
+++ b/src/cmd/link/internal/wasm/asm.go
@@ -39,7 +39,7 @@
 // funcValueOffset is the offset between the PC_F value of a function and the index of the function in WebAssembly
 const funcValueOffset = 0x1000 // TODO(neelance): make function addresses play nice with heap addresses
 
-func gentext2(ctxt *ld.Link, ldr *loader.Loader) {
+func gentext(ctxt *ld.Link, ldr *loader.Loader) {
 }
 
 type wasmFunc struct {
@@ -119,7 +119,7 @@
 
 // asmb writes the final WebAssembly module binary.
 // Spec: https://webassembly.github.io/spec/core/binary/modules.html
-func asmb2(ctxt *ld.Link) {
+func asmb2(ctxt *ld.Link, ldr *loader.Loader) {
 	types := []*wasmFuncType{
 		// For normal Go functions, the single parameter is PC_B,
 		// the return value is
@@ -135,13 +135,15 @@
 			Type: lookupType(&wasmFuncType{Params: []byte{I32}}, &types),
 		},
 	}
-	hostImportMap := make(map[*sym.Symbol]int64)
+	hostImportMap := make(map[loader.Sym]int64)
 	for _, fn := range ctxt.Textp {
-		for _, r := range fn.R {
-			if r.Type == objabi.R_WASMIMPORT {
-				hostImportMap[r.Sym] = int64(len(hostImports))
+		relocs := ldr.Relocs(fn)
+		for ri := 0; ri < relocs.Count(); ri++ {
+			r := relocs.At2(ri)
+			if r.Type() == objabi.R_WASMIMPORT {
+				hostImportMap[r.Sym()] = int64(len(hostImports))
 				hostImports = append(hostImports, &wasmFunc{
-					Name: r.Sym.Name,
+					Name: ldr.SymName(r.Sym()),
 					Type: lookupType(&wasmFuncType{Params: []byte{I32}}, &types),
 				})
 			}
@@ -153,38 +155,42 @@
 	fns := make([]*wasmFunc, len(ctxt.Textp))
 	for i, fn := range ctxt.Textp {
 		wfn := new(bytes.Buffer)
-		if fn.Name == "go.buildid" {
+		if ldr.SymName(fn) == "go.buildid" {
 			writeUleb128(wfn, 0) // number of sets of locals
 			writeI32Const(wfn, 0)
 			wfn.WriteByte(0x0b) // end
-			buildid = fn.P
+			buildid = ldr.Data(fn)
 		} else {
 			// Relocations have variable length, handle them here.
+			relocs := ldr.Relocs(fn)
+			P := ldr.Data(fn)
 			off := int32(0)
-			for _, r := range fn.R {
-				wfn.Write(fn.P[off:r.Off])
-				off = r.Off
-				switch r.Type {
+			for ri := 0; ri < relocs.Count(); ri++ {
+				r := relocs.At2(ri)
+				wfn.Write(P[off:r.Off()])
+				off = r.Off()
+				rs := ldr.ResolveABIAlias(r.Sym())
+				switch r.Type() {
 				case objabi.R_ADDR:
-					writeSleb128(wfn, r.Sym.Value+r.Add)
+					writeSleb128(wfn, ldr.SymValue(rs)+r.Add())
 				case objabi.R_CALL:
-					writeSleb128(wfn, int64(len(hostImports))+r.Sym.Value>>16-funcValueOffset)
+					writeSleb128(wfn, int64(len(hostImports))+ldr.SymValue(rs)>>16-funcValueOffset)
 				case objabi.R_WASMIMPORT:
-					writeSleb128(wfn, hostImportMap[r.Sym])
+					writeSleb128(wfn, hostImportMap[rs])
 				default:
-					ld.Errorf(fn, "bad reloc type %d (%s)", r.Type, sym.RelocName(ctxt.Arch, r.Type))
+					ldr.Errorf(fn, "bad reloc type %d (%s)", r.Type(), sym.RelocName(ctxt.Arch, r.Type()))
 					continue
 				}
 			}
-			wfn.Write(fn.P[off:])
+			wfn.Write(P[off:])
 		}
 
 		typ := uint32(0)
-		if sig, ok := wasmFuncTypes[fn.Name]; ok {
+		if sig, ok := wasmFuncTypes[ldr.SymName(fn)]; ok {
 			typ = lookupType(sig, &types)
 		}
 
-		name := nameRegexp.ReplaceAllString(fn.Name, "_")
+		name := nameRegexp.ReplaceAllString(ldr.SymName(fn), "_")
 		fns[i] = &wasmFunc{Name: name, Type: typ, Code: wfn.Bytes()}
 	}
 
@@ -200,9 +206,9 @@
 	writeImportSec(ctxt, hostImports)
 	writeFunctionSec(ctxt, fns)
 	writeTableSec(ctxt, fns)
-	writeMemorySec(ctxt)
+	writeMemorySec(ctxt, ldr)
 	writeGlobalSec(ctxt)
-	writeExportSec(ctxt, len(hostImports))
+	writeExportSec(ctxt, ldr, len(hostImports))
 	writeElementSec(ctxt, uint64(len(hostImports)), uint64(len(fns)))
 	writeCodeSec(ctxt, fns)
 	writeDataSec(ctxt)
@@ -311,10 +317,10 @@
 
 // writeMemorySec writes the section that declares linear memories. Currently one linear memory is being used.
 // Linear memory always starts at address zero. More memory can be requested with the GrowMemory instruction.
-func writeMemorySec(ctxt *ld.Link) {
+func writeMemorySec(ctxt *ld.Link, ldr *loader.Loader) {
 	sizeOffset := writeSecHeader(ctxt, sectionMemory)
 
-	dataSection := ctxt.Syms.Lookup("runtime.data", 0).Sect
+	dataSection := ldr.SymSect(ldr.Lookup("runtime.data", 0))
 	dataEnd := dataSection.Vaddr + dataSection.Length
 	var initialSize = dataEnd + 16<<20 // 16MB, enough for runtime init without growing
 
@@ -362,13 +368,14 @@
 // writeExportSec writes the section that declares exports.
 // Exports can be accessed by the WebAssembly host, usually JavaScript.
 // The wasm_export_* functions and the linear memory get exported.
-func writeExportSec(ctxt *ld.Link, lenHostImports int) {
+func writeExportSec(ctxt *ld.Link, ldr *loader.Loader, lenHostImports int) {
 	sizeOffset := writeSecHeader(ctxt, sectionExport)
 
 	writeUleb128(ctxt.Out, 4) // number of exports
 
 	for _, name := range []string{"run", "resume", "getsp"} {
-		idx := uint32(lenHostImports) + uint32(ctxt.Syms.ROLookup("wasm_export_"+name, 0).Value>>16) - funcValueOffset
+		s := ldr.Lookup("wasm_export_"+name, 0)
+		idx := uint32(lenHostImports) + uint32(ldr.SymValue(s)>>16) - funcValueOffset
 		writeName(ctxt.Out, name)           // inst.exports.run/resume/getsp in wasm_exec.js
 		ctxt.Out.WriteByte(0x00)            // func export
 		writeUleb128(ctxt.Out, uint64(idx)) // funcidx
diff --git a/src/cmd/link/internal/wasm/obj.go b/src/cmd/link/internal/wasm/obj.go
index 9fc1a6c..f8090a3 100644
--- a/src/cmd/link/internal/wasm/obj.go
+++ b/src/cmd/link/internal/wasm/obj.go
@@ -19,7 +19,7 @@
 		AssignAddress: assignAddress,
 		Asmb:          asmb,
 		Asmb2:         asmb2,
-		Gentext2:      gentext2,
+		Gentext:       gentext,
 	}
 
 	return sys.ArchWasm, theArch
diff --git a/src/cmd/link/internal/x86/asm.go b/src/cmd/link/internal/x86/asm.go
index b218ffa..6683c79 100644
--- a/src/cmd/link/internal/x86/asm.go
+++ b/src/cmd/link/internal/x86/asm.go
@@ -38,10 +38,9 @@
 	"cmd/link/internal/sym"
 	"debug/elf"
 	"log"
-	"sync"
 )
 
-func gentext2(ctxt *ld.Link, ldr *loader.Loader) {
+func gentext(ctxt *ld.Link, ldr *loader.Loader) {
 	if ctxt.DynlinkingGo() {
 		// We need get_pc_thunk.
 	} else {
@@ -58,7 +57,7 @@
 	}
 
 	// Generate little thunks that load the PC of the next instruction into a register.
-	thunks := make([]loader.Sym, 0, 7+len(ctxt.Textp2))
+	thunks := make([]loader.Sym, 0, 7+len(ctxt.Textp))
 	for _, r := range [...]struct {
 		name string
 		num  uint8
@@ -88,7 +87,7 @@
 
 		thunks = append(thunks, thunkfunc.Sym())
 	}
-	ctxt.Textp2 = append(thunks, ctxt.Textp2...) // keep Textp2 in dependency order
+	ctxt.Textp = append(thunks, ctxt.Textp...) // keep Textp in dependency order
 
 	initfunc, addmoduledata := ld.PrepareAddmoduledata(ctxt)
 	if initfunc == nil {
@@ -116,7 +115,7 @@
 	initfunc.AddSymRef(ctxt.Arch, ldr.Lookup("__x86.get_pc_thunk.cx", 0), 0, objabi.R_CALL, 4)
 
 	o(0x8d, 0x81)
-	initfunc.AddPCRelPlus(ctxt.Arch, ctxt.Moduledata2, 6)
+	initfunc.AddPCRelPlus(ctxt.Arch, ctxt.Moduledata, 6)
 
 	o(0x8d, 0x99)
 	gotsym := ldr.LookupOrCreateSym("_GLOBAL_OFFSET_TABLE_", 0)
@@ -129,7 +128,7 @@
 	o(0xc3)
 }
 
-func adddynrel2(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym, r loader.Reloc2, rIdx int) bool {
+func adddynrel(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym, r loader.Reloc2, rIdx int) bool {
 	targ := r.Sym()
 	var targType sym.SymKind
 	if targ != 0 {
@@ -163,8 +162,8 @@
 		su.SetRelocType(rIdx, objabi.R_PCREL)
 		su.SetRelocAdd(rIdx, r.Add()+4)
 		if targType == sym.SDYNIMPORT {
-			addpltsym2(target, ldr, syms, targ)
-			su.SetRelocSym(rIdx, syms.PLT2)
+			addpltsym(target, ldr, syms, targ)
+			su.SetRelocSym(rIdx, syms.PLT)
 			su.SetRelocAdd(rIdx, r.Add()+int64(ldr.SymPlt(targ)))
 		}
 
@@ -202,7 +201,7 @@
 			return false
 		}
 
-		addgotsym2(target, ldr, syms, targ)
+		ld.AddGotSym(target, ldr, syms, targ, uint32(elf.R_386_GLOB_DAT))
 		su.SetRelocType(rIdx, objabi.R_CONST) // write r->add during relocsym
 		su.SetRelocSym(rIdx, 0)
 		su.SetRelocAdd(rIdx, r.Add()+int64(ldr.SymGot(targ)))
@@ -216,7 +215,7 @@
 	case objabi.ElfRelocOffset + objabi.RelocType(elf.R_386_GOTPC):
 		su := ldr.MakeSymbolUpdater(s)
 		su.SetRelocType(rIdx, objabi.R_PCREL)
-		su.SetRelocSym(rIdx, syms.GOT2)
+		su.SetRelocSym(rIdx, syms.GOT)
 		su.SetRelocAdd(rIdx, r.Add()+4)
 		return true
 
@@ -239,8 +238,8 @@
 	case objabi.MachoRelocOffset + ld.MACHO_GENERIC_RELOC_VANILLA*2 + 1:
 		su := ldr.MakeSymbolUpdater(s)
 		if targType == sym.SDYNIMPORT {
-			addpltsym2(target, ldr, syms, targ)
-			su.SetRelocSym(rIdx, syms.PLT2)
+			addpltsym(target, ldr, syms, targ)
+			su.SetRelocSym(rIdx, syms.PLT)
 			su.SetRelocAdd(rIdx, int64(ldr.SymPlt(targ)))
 			su.SetRelocType(rIdx, objabi.R_PCREL)
 			return true
@@ -267,8 +266,8 @@
 			return true
 		}
 
-		addgotsym2(target, ldr, syms, targ)
-		su.SetRelocSym(rIdx, syms.GOT2)
+		ld.AddGotSym(target, ldr, syms, targ, uint32(elf.R_386_GLOB_DAT))
+		su.SetRelocSym(rIdx, syms.GOT)
 		su.SetRelocAdd(rIdx, r.Add()+int64(ldr.SymGot(targ)))
 		su.SetRelocType(rIdx, objabi.R_PCREL)
 		return true
@@ -290,9 +289,9 @@
 			// External linker will do this relocation.
 			return true
 		}
-		addpltsym2(target, ldr, syms, targ)
+		addpltsym(target, ldr, syms, targ)
 		su := ldr.MakeSymbolUpdater(s)
-		su.SetRelocSym(rIdx, syms.PLT2)
+		su.SetRelocSym(rIdx, syms.PLT)
 		su.SetRelocAdd(rIdx, int64(ldr.SymPlt(targ)))
 		return true
 
@@ -301,8 +300,8 @@
 			break
 		}
 		if target.IsElf() {
-			ld.Adddynsym2(ldr, target, syms, targ)
-			rel := ldr.MakeSymbolUpdater(syms.Rel2)
+			ld.Adddynsym(ldr, target, syms, targ)
+			rel := ldr.MakeSymbolUpdater(syms.Rel)
 			rel.AddAddrPlus(target.Arch, s, int64(r.Off()))
 			rel.AddUint32(target.Arch, ld.ELF32_R_INFO(uint32(ldr.SymDynid(targ)), uint32(elf.R_386_32)))
 			su := ldr.MakeSymbolUpdater(s)
@@ -310,53 +309,29 @@
 			su.SetRelocSym(rIdx, 0)
 			return true
 		}
-
-		if target.IsDarwin() && ldr.SymSize(s) == int64(target.Arch.PtrSize) && r.Off() == 0 {
-			// Mach-O relocations are a royal pain to lay out.
-			// They use a compact stateful bytecode representation
-			// that is too much bother to deal with.
-			// Instead, interpret the C declaration
-			//	void *_Cvar_stderr = &stderr;
-			// as making _Cvar_stderr the name of a GOT entry
-			// for stderr. This is separate from the usual GOT entry,
-			// just in case the C code assigns to the variable,
-			// and of course it only works for single pointers,
-			// but we only need to support cgo and that's all it needs.
-			ld.Adddynsym2(ldr, target, syms, targ)
-
-			got := ldr.MakeSymbolUpdater(syms.GOT2)
-			su := ldr.MakeSymbolUpdater(s)
-			su.SetType(got.Type())
-			got.PrependSub(s)
-			su.SetValue(got.Size())
-			got.AddUint32(target.Arch, 0)
-			leg := ldr.MakeSymbolUpdater(syms.LinkEditGOT2)
-			leg.AddUint32(target.Arch, uint32(ldr.SymDynid(targ)))
-			su.SetRelocType(rIdx, objabi.ElfRelocOffset) // ignore during relocsym
-			return true
-		}
 	}
 
 	return false
 }
 
-func elfreloc1(ctxt *ld.Link, r *sym.Reloc, sectoff int64) bool {
+func elfreloc1(ctxt *ld.Link, ldr *loader.Loader, s loader.Sym, r loader.ExtRelocView, sectoff int64) bool {
 	ctxt.Out.Write32(uint32(sectoff))
 
 	elfsym := ld.ElfSymForReloc(ctxt, r.Xsym)
-	switch r.Type {
+	siz := r.Siz()
+	switch r.Type() {
 	default:
 		return false
 	case objabi.R_ADDR, objabi.R_DWARFSECREF:
-		if r.Siz == 4 {
+		if siz == 4 {
 			ctxt.Out.Write32(uint32(elf.R_386_32) | uint32(elfsym)<<8)
 		} else {
 			return false
 		}
 	case objabi.R_GOTPCREL:
-		if r.Siz == 4 {
+		if siz == 4 {
 			ctxt.Out.Write32(uint32(elf.R_386_GOTPC))
-			if r.Xsym.Name != "_GLOBAL_OFFSET_TABLE_" {
+			if ldr.SymName(r.Xsym) != "_GLOBAL_OFFSET_TABLE_" {
 				ctxt.Out.Write32(uint32(sectoff))
 				ctxt.Out.Write32(uint32(elf.R_386_GOT32) | uint32(elfsym)<<8)
 			}
@@ -364,8 +339,8 @@
 			return false
 		}
 	case objabi.R_CALL:
-		if r.Siz == 4 {
-			if r.Xsym.Type == sym.SDYNIMPORT {
+		if siz == 4 {
+			if ldr.SymType(r.Xsym) == sym.SDYNIMPORT {
 				ctxt.Out.Write32(uint32(elf.R_386_PLT32) | uint32(elfsym)<<8)
 			} else {
 				ctxt.Out.Write32(uint32(elf.R_386_PC32) | uint32(elfsym)<<8)
@@ -374,19 +349,19 @@
 			return false
 		}
 	case objabi.R_PCREL:
-		if r.Siz == 4 {
+		if siz == 4 {
 			ctxt.Out.Write32(uint32(elf.R_386_PC32) | uint32(elfsym)<<8)
 		} else {
 			return false
 		}
 	case objabi.R_TLS_LE:
-		if r.Siz == 4 {
+		if siz == 4 {
 			ctxt.Out.Write32(uint32(elf.R_386_TLS_LE) | uint32(elfsym)<<8)
 		} else {
 			return false
 		}
 	case objabi.R_TLS_IE:
-		if r.Siz == 4 {
+		if siz == 4 {
 			ctxt.Out.Write32(uint32(elf.R_386_GOTPC))
 			ctxt.Out.Write32(uint32(sectoff))
 			ctxt.Out.Write32(uint32(elf.R_386_TLS_GOTIE) | uint32(elfsym)<<8)
@@ -398,24 +373,25 @@
 	return true
 }
 
-func machoreloc1(arch *sys.Arch, out *ld.OutBuf, s *sym.Symbol, r *sym.Reloc, sectoff int64) bool {
+func machoreloc1(*sys.Arch, *ld.OutBuf, *loader.Loader, loader.Sym, loader.ExtRelocView, int64) bool {
 	return false
 }
 
-func pereloc1(arch *sys.Arch, out *ld.OutBuf, s *sym.Symbol, r *sym.Reloc, sectoff int64) bool {
+func pereloc1(arch *sys.Arch, out *ld.OutBuf, ldr *loader.Loader, s loader.Sym, r loader.ExtRelocView, sectoff int64) bool {
 	var v uint32
 
 	rs := r.Xsym
+	rt := r.Type()
 
-	if rs.Dynid < 0 {
-		ld.Errorf(s, "reloc %d (%s) to non-coff symbol %s type=%d (%s)", r.Type, sym.RelocName(arch, r.Type), rs.Name, rs.Type, rs.Type)
+	if ldr.SymDynid(rs) < 0 {
+		ldr.Errorf(s, "reloc %d (%s) to non-coff symbol %s type=%d (%s)", rt, sym.RelocName(arch, rt), ldr.SymName(rs), ldr.SymType(rs), ldr.SymType(rs))
 		return false
 	}
 
 	out.Write32(uint32(sectoff))
-	out.Write32(uint32(rs.Dynid))
+	out.Write32(uint32(ldr.SymDynid(rs)))
 
-	switch r.Type {
+	switch rt {
 	default:
 		return false
 
@@ -435,13 +411,13 @@
 	return true
 }
 
-func archreloc2(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loader.Reloc2, rr *loader.ExtReloc, sym loader.Sym, val int64) (int64, bool, bool) {
-	return val, false, false
+func archreloc(*ld.Target, *loader.Loader, *ld.ArchSyms, loader.Reloc2, *loader.ExtReloc, loader.Sym, int64) (int64, bool, bool) {
+	return -1, false, false
 }
 
-func archrelocvariant(target *ld.Target, syms *ld.ArchSyms, r *sym.Reloc, s *sym.Symbol, t int64) int64 {
+func archrelocvariant(*ld.Target, *loader.Loader, loader.Reloc2, sym.RelocVariant, loader.Sym, int64) int64 {
 	log.Fatalf("unexpected relocation variant")
-	return t
+	return -1
 }
 
 func elfsetupplt(ctxt *ld.Link, plt, got *loader.SymbolBuilder, dynamic loader.Sym) {
@@ -469,17 +445,17 @@
 	}
 }
 
-func addpltsym2(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym) {
+func addpltsym(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym) {
 	if ldr.SymPlt(s) >= 0 {
 		return
 	}
 
-	ld.Adddynsym2(ldr, target, syms, s)
+	ld.Adddynsym(ldr, target, syms, s)
 
 	if target.IsElf() {
-		plt := ldr.MakeSymbolUpdater(syms.PLT2)
-		got := ldr.MakeSymbolUpdater(syms.GOTPLT2)
-		rel := ldr.MakeSymbolUpdater(syms.RelPLT2)
+		plt := ldr.MakeSymbolUpdater(syms.PLT)
+		got := ldr.MakeSymbolUpdater(syms.GOTPLT)
+		rel := ldr.MakeSymbolUpdater(syms.RelPLT)
 		if plt.Size() == 0 {
 			panic("plt is not set up")
 		}
@@ -510,168 +486,7 @@
 		rel.AddUint32(target.Arch, ld.ELF32_R_INFO(uint32(sDynid), uint32(elf.R_386_JMP_SLOT)))
 
 		ldr.SetPlt(s, int32(plt.Size()-16))
-	} else if target.IsDarwin() {
-		// Same laziness as in 6l.
-
-		plt := ldr.MakeSymbolUpdater(syms.PLT2)
-
-		addgotsym2(target, ldr, syms, s)
-
-		sDynid := ldr.SymDynid(s)
-		lep := ldr.MakeSymbolUpdater(syms.LinkEditPLT2)
-		lep.AddUint32(target.Arch, uint32(sDynid))
-
-		// jmpq *got+size(IP)
-		ldr.SetPlt(s, int32(plt.Size()))
-
-		plt.AddUint8(0xff)
-		plt.AddUint8(0x25)
-		plt.AddAddrPlus(target.Arch, syms.GOT2, int64(ldr.SymGot(s)))
 	} else {
 		ldr.Errorf(s, "addpltsym: unsupported binary format")
 	}
 }
-
-func addgotsym2(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym) {
-	if ldr.SymGot(s) >= 0 {
-		return
-	}
-
-	ld.Adddynsym2(ldr, target, syms, s)
-	got := ldr.MakeSymbolUpdater(syms.GOT2)
-	ldr.SetGot(s, int32(got.Size()))
-	got.AddUint32(target.Arch, 0)
-
-	if target.IsElf() {
-		rel := ldr.MakeSymbolUpdater(syms.Rel2)
-		rel.AddAddrPlus(target.Arch, got.Sym(), int64(ldr.SymGot(s)))
-		rel.AddUint32(target.Arch, ld.ELF32_R_INFO(uint32(ldr.SymDynid(s)), uint32(elf.R_386_GLOB_DAT)))
-	} else if target.IsDarwin() {
-		leg := ldr.MakeSymbolUpdater(syms.LinkEditGOT2)
-		leg.AddUint32(target.Arch, uint32(ldr.SymDynid(s)))
-	} else {
-		ldr.Errorf(s, "addgotsym: unsupported binary format")
-	}
-}
-
-func asmb(ctxt *ld.Link, _ *loader.Loader) {
-	if ctxt.IsELF {
-		ld.Asmbelfsetup()
-	}
-
-	var wg sync.WaitGroup
-	sect := ld.Segtext.Sections[0]
-	offset := sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff
-	f := func(ctxt *ld.Link, out *ld.OutBuf, start, length int64) {
-		ld.CodeblkPad(ctxt, out, start, length, []byte{0xCC})
-	}
-	ld.WriteParallel(&wg, f, ctxt, offset, sect.Vaddr, sect.Length)
-
-	for _, sect := range ld.Segtext.Sections[1:] {
-		offset := sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff
-		ld.WriteParallel(&wg, ld.Datblk, ctxt, offset, sect.Vaddr, sect.Length)
-	}
-
-	if ld.Segrodata.Filelen > 0 {
-		ld.WriteParallel(&wg, ld.Datblk, ctxt, ld.Segrodata.Fileoff, ld.Segrodata.Vaddr, ld.Segrodata.Filelen)
-	}
-
-	if ld.Segrelrodata.Filelen > 0 {
-		ld.WriteParallel(&wg, ld.Datblk, ctxt, ld.Segrelrodata.Fileoff, ld.Segrelrodata.Vaddr, ld.Segrelrodata.Filelen)
-	}
-
-	ld.WriteParallel(&wg, ld.Datblk, ctxt, ld.Segdata.Fileoff, ld.Segdata.Vaddr, ld.Segdata.Filelen)
-
-	ld.WriteParallel(&wg, ld.Dwarfblk, ctxt, ld.Segdwarf.Fileoff, ld.Segdwarf.Vaddr, ld.Segdwarf.Filelen)
-	wg.Wait()
-}
-
-func asmb2(ctxt *ld.Link) {
-	machlink := uint32(0)
-	if ctxt.HeadType == objabi.Hdarwin {
-		machlink = uint32(ld.Domacholink(ctxt))
-	}
-
-	ld.Symsize = 0
-	ld.Spsize = 0
-	ld.Lcsize = 0
-	symo := uint32(0)
-	if !*ld.FlagS {
-		// TODO: rationalize
-		switch ctxt.HeadType {
-		default:
-			if ctxt.IsELF {
-				symo = uint32(ld.Segdwarf.Fileoff + ld.Segdwarf.Filelen)
-				symo = uint32(ld.Rnd(int64(symo), int64(*ld.FlagRound)))
-			}
-
-		case objabi.Hplan9:
-			symo = uint32(ld.Segdata.Fileoff + ld.Segdata.Filelen)
-
-		case objabi.Hdarwin:
-			symo = uint32(ld.Segdwarf.Fileoff + uint64(ld.Rnd(int64(ld.Segdwarf.Filelen), int64(*ld.FlagRound))) + uint64(machlink))
-
-		case objabi.Hwindows:
-			symo = uint32(ld.Segdwarf.Fileoff + ld.Segdwarf.Filelen)
-			symo = uint32(ld.Rnd(int64(symo), ld.PEFILEALIGN))
-		}
-
-		ctxt.Out.SeekSet(int64(symo))
-		switch ctxt.HeadType {
-		default:
-			if ctxt.IsELF {
-				ld.Asmelfsym(ctxt)
-				ctxt.Out.Write(ld.Elfstrdat)
-
-				if ctxt.LinkMode == ld.LinkExternal {
-					ld.Elfemitreloc(ctxt)
-				}
-			}
-
-		case objabi.Hplan9:
-			ld.Asmplan9sym(ctxt)
-
-			sym := ctxt.Syms.Lookup("pclntab", 0)
-			if sym != nil {
-				ld.Lcsize = int32(len(sym.P))
-				ctxt.Out.Write(sym.P)
-			}
-
-		case objabi.Hwindows:
-			// Do nothing
-
-		case objabi.Hdarwin:
-			if ctxt.LinkMode == ld.LinkExternal {
-				ld.Machoemitreloc(ctxt)
-			}
-		}
-	}
-
-	ctxt.Out.SeekSet(0)
-	switch ctxt.HeadType {
-	default:
-	case objabi.Hplan9: /* plan9 */
-		magic := int32(4*11*11 + 7)
-
-		ctxt.Out.Write32b(uint32(magic))              /* magic */
-		ctxt.Out.Write32b(uint32(ld.Segtext.Filelen)) /* sizes */
-		ctxt.Out.Write32b(uint32(ld.Segdata.Filelen))
-		ctxt.Out.Write32b(uint32(ld.Segdata.Length - ld.Segdata.Filelen))
-		ctxt.Out.Write32b(uint32(ld.Symsize))          /* nsyms */
-		ctxt.Out.Write32b(uint32(ld.Entryvalue(ctxt))) /* va of entry */
-		ctxt.Out.Write32b(uint32(ld.Spsize))           /* sp offsets */
-		ctxt.Out.Write32b(uint32(ld.Lcsize))           /* line offsets */
-
-	case objabi.Hdarwin:
-		ld.Asmbmacho(ctxt)
-
-	case objabi.Hlinux,
-		objabi.Hfreebsd,
-		objabi.Hnetbsd,
-		objabi.Hopenbsd:
-		ld.Asmbelf(ctxt, int64(symo))
-
-	case objabi.Hwindows:
-		ld.Asmbpe(ctxt)
-	}
-}
diff --git a/src/cmd/link/internal/x86/obj.go b/src/cmd/link/internal/x86/obj.go
index cd33f44..e1c469c 100644
--- a/src/cmd/link/internal/x86/obj.go
+++ b/src/cmd/link/internal/x86/obj.go
@@ -45,16 +45,18 @@
 		Minalign:   minAlign,
 		Dwarfregsp: dwarfRegSP,
 		Dwarfreglr: dwarfRegLR,
+		// 0xCC is INT $3 - breakpoint instruction
+		CodePad: []byte{0xCC},
 
-		Adddynrel2:       adddynrel2,
+		Plan9Magic: uint32(4*11*11 + 7),
+
+		Adddynrel:        adddynrel,
 		Archinit:         archinit,
-		Archreloc2:       archreloc2,
+		Archreloc:        archreloc,
 		Archrelocvariant: archrelocvariant,
-		Asmb:             asmb,
-		Asmb2:            asmb2,
 		Elfreloc1:        elfreloc1,
 		Elfsetupplt:      elfsetupplt,
-		Gentext2:         gentext2,
+		Gentext:          gentext,
 		Machoreloc1:      machoreloc1,
 		PEreloc1:         pereloc1,
 
diff --git a/src/cmd/link/link_test.go b/src/cmd/link/link_test.go
index 5ff9912..635c55d 100644
--- a/src/cmd/link/link_test.go
+++ b/src/cmd/link/link_test.go
@@ -535,30 +535,6 @@
 	}
 }
 
-func TestOldLink(t *testing.T) {
-	// Test that old object file format still works.
-	// TODO(go115newobj): delete.
-
-	testenv.MustHaveGoBuild(t)
-
-	tmpdir, err := ioutil.TempDir("", "TestOldLink")
-	if err != nil {
-		t.Fatal(err)
-	}
-	defer os.RemoveAll(tmpdir)
-
-	src := filepath.Join(tmpdir, "main.go")
-	err = ioutil.WriteFile(src, []byte("package main; func main(){}\n"), 0666)
-	if err != nil {
-		t.Fatal(err)
-	}
-
-	cmd := exec.Command(testenv.GoToolPath(t), "run", "-gcflags=all=-go115newobj=false", "-asmflags=all=-go115newobj=false", "-ldflags=-go115newobj=false", src)
-	if out, err := cmd.CombinedOutput(); err != nil {
-		t.Errorf("%v: %v:\n%s", cmd.Args, err, out)
-	}
-}
-
 const testFuncAlignSrc = `
 package main
 import (
diff --git a/src/cmd/oldlink/doc.go b/src/cmd/oldlink/doc.go
deleted file mode 100644
index 219499b..0000000
--- a/src/cmd/oldlink/doc.go
+++ /dev/null
@@ -1,129 +0,0 @@
-// Copyright 2009 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.
-
-/*
-Link, typically invoked as ``go tool link,'' reads the Go archive or object
-for a package main, along with its dependencies, and combines them
-into an executable binary.
-
-Command Line
-
-Usage:
-
-	go tool link [flags] main.a
-
-Flags:
-
-	-B note
-		Add an ELF_NT_GNU_BUILD_ID note when using ELF.
-		The value should start with 0x and be an even number of hex digits.
-	-D address
-		Set data segment address.
-	-E entry
-		Set entry symbol name.
-	-H type
-		Set executable format type.
-		The default format is inferred from GOOS and GOARCH.
-		On Windows, -H windowsgui writes a "GUI binary" instead of a "console binary."
-	-I interpreter
-		Set the ELF dynamic linker to use.
-	-L dir1 -L dir2
-		Search for imported packages in dir1, dir2, etc,
-		after consulting $GOROOT/pkg/$GOOS_$GOARCH.
-	-R quantum
-		Set address rounding quantum.
-	-T address
-		Set text segment address.
-	-V
-		Print linker version and exit.
-	-X importpath.name=value
-		Set the value of the string variable in importpath named name to value.
-		This is only effective if the variable is declared in the source code either uninitialized
-		or initialized to a constant string expression. -X will not work if the initializer makes
-		a function call or refers to other variables.
-		Note that before Go 1.5 this option took two separate arguments.
-	-a
-		Disassemble output.
-	-buildid id
-		Record id as Go toolchain build id.
-	-buildmode mode
-		Set build mode (default exe).
-	-c
-		Dump call graphs.
-	-compressdwarf
-		Compress DWARF if possible (default true).
-	-cpuprofile file
-		Write CPU profile to file.
-	-d
-		Disable generation of dynamic executables.
-		The emitted code is the same in either case; the option
-		controls only whether a dynamic header is included.
-		The dynamic header is on by default, even without any
-		references to dynamic libraries, because many common
-		system tools now assume the presence of the header.
-	-debugtramp int
-		Debug trampolines.
-	-dumpdep
-		Dump symbol dependency graph.
-	-extar ar
-		Set the external archive program (default "ar").
-		Used only for -buildmode=c-archive.
-	-extld linker
-		Set the external linker (default "clang" or "gcc").
-	-extldflags flags
-		Set space-separated flags to pass to the external linker.
-	-f
-		Ignore version mismatch in the linked archives.
-	-g
-		Disable Go package data checks.
-	-importcfg file
-		Read import configuration from file.
-		In the file, set packagefile, packageshlib to specify import resolution.
-	-installsuffix suffix
-		Look for packages in $GOROOT/pkg/$GOOS_$GOARCH_suffix
-		instead of $GOROOT/pkg/$GOOS_$GOARCH.
-	-k symbol
-		Set field tracking symbol. Use this flag when GOEXPERIMENT=fieldtrack is set.
-	-libgcc file
-		Set name of compiler support library.
-		This is only used in internal link mode.
-		If not set, default value comes from running the compiler,
-		which may be set by the -extld option.
-		Set to "none" to use no support library.
-	-linkmode mode
-		Set link mode (internal, external, auto).
-		This sets the linking mode as described in cmd/cgo/doc.go.
-	-linkshared
-		Link against installed Go shared libraries (experimental).
-	-memprofile file
-		Write memory profile to file.
-	-memprofilerate rate
-		Set runtime.MemProfileRate to rate.
-	-msan
-		Link with C/C++ memory sanitizer support.
-	-n
-		Dump symbol table.
-	-o file
-		Write output to file (default a.out, or a.out.exe on Windows).
-	-pluginpath path
-		The path name used to prefix exported plugin symbols.
-	-r dir1:dir2:...
-		Set the ELF dynamic linker search path.
-	-race
-		Link with race detection libraries.
-	-s
-		Omit the symbol table and debug information.
-	-shared
-		Generated shared object (implies -linkmode external; experimental).
-	-tmpdir dir
-		Write temporary files to dir.
-		Temporary files are only used in external linking mode.
-	-u
-		Reject unsafe packages.
-	-v
-		Print trace of linker operations.
-	-w
-		Omit the DWARF symbol table.
-*/
-package main
diff --git a/src/cmd/oldlink/internal/amd64/asm.go b/src/cmd/oldlink/internal/amd64/asm.go
deleted file mode 100644
index 13baf3e..0000000
--- a/src/cmd/oldlink/internal/amd64/asm.go
+++ /dev/null
@@ -1,874 +0,0 @@
-// Inferno utils/6l/asm.c
-// https://bitbucket.org/inferno-os/inferno-os/src/master/utils/6l/asm.c
-//
-//	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 amd64
-
-import (
-	"cmd/internal/objabi"
-	"cmd/internal/sys"
-	"cmd/oldlink/internal/ld"
-	"cmd/oldlink/internal/sym"
-	"debug/elf"
-	"log"
-)
-
-func PADDR(x uint32) uint32 {
-	return x &^ 0x80000000
-}
-
-func Addcall(ctxt *ld.Link, s *sym.Symbol, t *sym.Symbol) int64 {
-	s.Attr |= sym.AttrReachable
-	i := s.Size
-	s.Size += 4
-	s.Grow(s.Size)
-	r := s.AddRel()
-	r.Sym = t
-	r.Off = int32(i)
-	r.Type = objabi.R_CALL
-	r.Siz = 4
-	return i + int64(r.Siz)
-}
-
-func gentext(ctxt *ld.Link) {
-	if !ctxt.DynlinkingGo() {
-		return
-	}
-	addmoduledata := ctxt.Syms.Lookup("runtime.addmoduledata", 0)
-	if addmoduledata.Type == sym.STEXT && ctxt.BuildMode != ld.BuildModePlugin {
-		// we're linking a module containing the runtime -> no need for
-		// an init function
-		return
-	}
-	addmoduledata.Attr |= sym.AttrReachable
-	initfunc := ctxt.Syms.Lookup("go.link.addmoduledata", 0)
-	initfunc.Type = sym.STEXT
-	initfunc.Attr |= sym.AttrLocal
-	initfunc.Attr |= sym.AttrReachable
-	o := func(op ...uint8) {
-		for _, op1 := range op {
-			initfunc.AddUint8(op1)
-		}
-	}
-	// 0000000000000000 <local.dso_init>:
-	//    0:	48 8d 3d 00 00 00 00 	lea    0x0(%rip),%rdi        # 7 <local.dso_init+0x7>
-	// 			3: R_X86_64_PC32	runtime.firstmoduledata-0x4
-	o(0x48, 0x8d, 0x3d)
-	initfunc.AddPCRelPlus(ctxt.Arch, ctxt.Moduledata, 0)
-	//    7:	e8 00 00 00 00       	callq  c <local.dso_init+0xc>
-	// 			8: R_X86_64_PLT32	runtime.addmoduledata-0x4
-	o(0xe8)
-	Addcall(ctxt, initfunc, addmoduledata)
-	//    c:	c3                   	retq
-	o(0xc3)
-	if ctxt.BuildMode == ld.BuildModePlugin {
-		ctxt.Textp = append(ctxt.Textp, addmoduledata)
-	}
-	ctxt.Textp = append(ctxt.Textp, initfunc)
-	initarray_entry := ctxt.Syms.Lookup("go.link.addmoduledatainit", 0)
-	initarray_entry.Attr |= sym.AttrReachable
-	initarray_entry.Attr |= sym.AttrLocal
-	initarray_entry.Type = sym.SINITARR
-	initarray_entry.AddAddr(ctxt.Arch, initfunc)
-}
-
-func adddynrel(ctxt *ld.Link, s *sym.Symbol, r *sym.Reloc) bool {
-	targ := r.Sym
-
-	switch r.Type {
-	default:
-		if r.Type >= objabi.ElfRelocOffset {
-			ld.Errorf(s, "unexpected relocation type %d (%s)", r.Type, sym.RelocName(ctxt.Arch, r.Type))
-			return false
-		}
-
-		// Handle relocations found in ELF object files.
-	case objabi.ElfRelocOffset + objabi.RelocType(elf.R_X86_64_PC32):
-		if targ.Type == sym.SDYNIMPORT {
-			ld.Errorf(s, "unexpected R_X86_64_PC32 relocation for dynamic symbol %s", targ.Name)
-		}
-		// TODO(mwhudson): the test of VisibilityHidden here probably doesn't make
-		// sense and should be removed when someone has thought about it properly.
-		if (targ.Type == 0 || targ.Type == sym.SXREF) && !targ.Attr.VisibilityHidden() {
-			ld.Errorf(s, "unknown symbol %s in pcrel", targ.Name)
-		}
-		r.Type = objabi.R_PCREL
-		r.Add += 4
-		return true
-
-	case objabi.ElfRelocOffset + objabi.RelocType(elf.R_X86_64_PC64):
-		if targ.Type == sym.SDYNIMPORT {
-			ld.Errorf(s, "unexpected R_X86_64_PC64 relocation for dynamic symbol %s", targ.Name)
-		}
-		if targ.Type == 0 || targ.Type == sym.SXREF {
-			ld.Errorf(s, "unknown symbol %s in pcrel", targ.Name)
-		}
-		r.Type = objabi.R_PCREL
-		r.Add += 8
-		return true
-
-	case objabi.ElfRelocOffset + objabi.RelocType(elf.R_X86_64_PLT32):
-		r.Type = objabi.R_PCREL
-		r.Add += 4
-		if targ.Type == sym.SDYNIMPORT {
-			addpltsym(ctxt, targ)
-			r.Sym = ctxt.Syms.Lookup(".plt", 0)
-			r.Add += int64(targ.Plt())
-		}
-
-		return true
-
-	case objabi.ElfRelocOffset + objabi.RelocType(elf.R_X86_64_GOTPCREL),
-		objabi.ElfRelocOffset + objabi.RelocType(elf.R_X86_64_GOTPCRELX),
-		objabi.ElfRelocOffset + objabi.RelocType(elf.R_X86_64_REX_GOTPCRELX):
-		if targ.Type != sym.SDYNIMPORT {
-			// have symbol
-			if r.Off >= 2 && s.P[r.Off-2] == 0x8b {
-				// turn MOVQ of GOT entry into LEAQ of symbol itself
-				s.P[r.Off-2] = 0x8d
-
-				r.Type = objabi.R_PCREL
-				r.Add += 4
-				return true
-			}
-		}
-
-		// fall back to using GOT and hope for the best (CMOV*)
-		// TODO: just needs relocation, no need to put in .dynsym
-		addgotsym(ctxt, targ)
-
-		r.Type = objabi.R_PCREL
-		r.Sym = ctxt.Syms.Lookup(".got", 0)
-		r.Add += 4
-		r.Add += int64(targ.Got())
-		return true
-
-	case objabi.ElfRelocOffset + objabi.RelocType(elf.R_X86_64_64):
-		if targ.Type == sym.SDYNIMPORT {
-			ld.Errorf(s, "unexpected R_X86_64_64 relocation for dynamic symbol %s", targ.Name)
-		}
-		r.Type = objabi.R_ADDR
-		if ctxt.BuildMode == ld.BuildModePIE && ctxt.LinkMode == ld.LinkInternal {
-			// For internal linking PIE, this R_ADDR relocation cannot
-			// be resolved statically. We need to generate a dynamic
-			// relocation. Let the code below handle it.
-			break
-		}
-		return true
-
-	// Handle relocations found in Mach-O object files.
-	case objabi.MachoRelocOffset + ld.MACHO_X86_64_RELOC_UNSIGNED*2 + 0,
-		objabi.MachoRelocOffset + ld.MACHO_X86_64_RELOC_SIGNED*2 + 0,
-		objabi.MachoRelocOffset + ld.MACHO_X86_64_RELOC_BRANCH*2 + 0:
-		// TODO: What is the difference between all these?
-		r.Type = objabi.R_ADDR
-
-		if targ.Type == sym.SDYNIMPORT {
-			ld.Errorf(s, "unexpected reloc for dynamic symbol %s", targ.Name)
-		}
-		return true
-
-	case objabi.MachoRelocOffset + ld.MACHO_X86_64_RELOC_BRANCH*2 + 1:
-		if targ.Type == sym.SDYNIMPORT {
-			addpltsym(ctxt, targ)
-			r.Sym = ctxt.Syms.Lookup(".plt", 0)
-			r.Add = int64(targ.Plt())
-			r.Type = objabi.R_PCREL
-			return true
-		}
-		fallthrough
-
-	case objabi.MachoRelocOffset + ld.MACHO_X86_64_RELOC_UNSIGNED*2 + 1,
-		objabi.MachoRelocOffset + ld.MACHO_X86_64_RELOC_SIGNED*2 + 1,
-		objabi.MachoRelocOffset + ld.MACHO_X86_64_RELOC_SIGNED_1*2 + 1,
-		objabi.MachoRelocOffset + ld.MACHO_X86_64_RELOC_SIGNED_2*2 + 1,
-		objabi.MachoRelocOffset + ld.MACHO_X86_64_RELOC_SIGNED_4*2 + 1:
-		r.Type = objabi.R_PCREL
-
-		if targ.Type == sym.SDYNIMPORT {
-			ld.Errorf(s, "unexpected pc-relative reloc for dynamic symbol %s", targ.Name)
-		}
-		return true
-
-	case objabi.MachoRelocOffset + ld.MACHO_X86_64_RELOC_GOT_LOAD*2 + 1:
-		if targ.Type != sym.SDYNIMPORT {
-			// have symbol
-			// turn MOVQ of GOT entry into LEAQ of symbol itself
-			if r.Off < 2 || s.P[r.Off-2] != 0x8b {
-				ld.Errorf(s, "unexpected GOT_LOAD reloc for non-dynamic symbol %s", targ.Name)
-				return false
-			}
-
-			s.P[r.Off-2] = 0x8d
-			r.Type = objabi.R_PCREL
-			return true
-		}
-		fallthrough
-
-	case objabi.MachoRelocOffset + ld.MACHO_X86_64_RELOC_GOT*2 + 1:
-		if targ.Type != sym.SDYNIMPORT {
-			ld.Errorf(s, "unexpected GOT reloc for non-dynamic symbol %s", targ.Name)
-		}
-		addgotsym(ctxt, targ)
-		r.Type = objabi.R_PCREL
-		r.Sym = ctxt.Syms.Lookup(".got", 0)
-		r.Add += int64(targ.Got())
-		return true
-	}
-
-	switch r.Type {
-	case objabi.R_CALL,
-		objabi.R_PCREL:
-		if targ.Type != sym.SDYNIMPORT {
-			// nothing to do, the relocation will be laid out in reloc
-			return true
-		}
-		if ctxt.LinkMode == ld.LinkExternal {
-			// External linker will do this relocation.
-			return true
-		}
-		// Internal linking, for both ELF and Mach-O.
-		// Build a PLT entry and change the relocation target to that entry.
-		addpltsym(ctxt, targ)
-		r.Sym = ctxt.Syms.Lookup(".plt", 0)
-		r.Add = int64(targ.Plt())
-		return true
-
-	case objabi.R_ADDR:
-		if s.Type == sym.STEXT && ctxt.IsELF {
-			if ctxt.HeadType == objabi.Hsolaris {
-				addpltsym(ctxt, targ)
-				r.Sym = ctxt.Syms.Lookup(".plt", 0)
-				r.Add += int64(targ.Plt())
-				return true
-			}
-			// The code is asking for the address of an external
-			// function. We provide it with the address of the
-			// correspondent GOT symbol.
-			addgotsym(ctxt, targ)
-
-			r.Sym = ctxt.Syms.Lookup(".got", 0)
-			r.Add += int64(targ.Got())
-			return true
-		}
-
-		// Process dynamic relocations for the data sections.
-		if ctxt.BuildMode == ld.BuildModePIE && ctxt.LinkMode == ld.LinkInternal {
-			// When internally linking, generate dynamic relocations
-			// for all typical R_ADDR relocations. The exception
-			// are those R_ADDR that are created as part of generating
-			// the dynamic relocations and must be resolved statically.
-			//
-			// There are three phases relevant to understanding this:
-			//
-			//	dodata()  // we are here
-			//	address() // symbol address assignment
-			//	reloc()   // resolution of static R_ADDR relocs
-			//
-			// At this point symbol addresses have not been
-			// assigned yet (as the final size of the .rela section
-			// will affect the addresses), and so we cannot write
-			// the Elf64_Rela.r_offset now. Instead we delay it
-			// until after the 'address' phase of the linker is
-			// complete. We do this via Addaddrplus, which creates
-			// a new R_ADDR relocation which will be resolved in
-			// the 'reloc' phase.
-			//
-			// These synthetic static R_ADDR relocs must be skipped
-			// now, or else we will be caught in an infinite loop
-			// of generating synthetic relocs for our synthetic
-			// relocs.
-			//
-			// Furthermore, the rela sections contain dynamic
-			// relocations with R_ADDR relocations on
-			// Elf64_Rela.r_offset. This field should contain the
-			// symbol offset as determined by reloc(), not the
-			// final dynamically linked address as a dynamic
-			// relocation would provide.
-			switch s.Name {
-			case ".dynsym", ".rela", ".rela.plt", ".got.plt", ".dynamic":
-				return false
-			}
-		} else {
-			// Either internally linking a static executable,
-			// in which case we can resolve these relocations
-			// statically in the 'reloc' phase, or externally
-			// linking, in which case the relocation will be
-			// prepared in the 'reloc' phase and passed to the
-			// external linker in the 'asmb' phase.
-			if s.Type != sym.SDATA && s.Type != sym.SRODATA {
-				break
-			}
-		}
-
-		if ctxt.IsELF {
-			// Generate R_X86_64_RELATIVE relocations for best
-			// efficiency in the dynamic linker.
-			//
-			// As noted above, symbol addresses have not been
-			// assigned yet, so we can't generate the final reloc
-			// entry yet. We ultimately want:
-			//
-			// r_offset = s + r.Off
-			// r_info = R_X86_64_RELATIVE
-			// r_addend = targ + r.Add
-			//
-			// The dynamic linker will set *offset = base address +
-			// addend.
-			//
-			// AddAddrPlus is used for r_offset and r_addend to
-			// generate new R_ADDR relocations that will update
-			// these fields in the 'reloc' phase.
-			rela := ctxt.Syms.Lookup(".rela", 0)
-			rela.AddAddrPlus(ctxt.Arch, s, int64(r.Off))
-			if r.Siz == 8 {
-				rela.AddUint64(ctxt.Arch, ld.ELF64_R_INFO(0, uint32(elf.R_X86_64_RELATIVE)))
-			} else {
-				ld.Errorf(s, "unexpected relocation for dynamic symbol %s", targ.Name)
-			}
-			rela.AddAddrPlus(ctxt.Arch, targ, int64(r.Add))
-			// Not mark r done here. So we still apply it statically,
-			// so in the file content we'll also have the right offset
-			// to the relocation target. So it can be examined statically
-			// (e.g. go version).
-			return true
-		}
-
-		if ctxt.HeadType == objabi.Hdarwin && s.Size == int64(ctxt.Arch.PtrSize) && r.Off == 0 {
-			// Mach-O relocations are a royal pain to lay out.
-			// They use a compact stateful bytecode representation
-			// that is too much bother to deal with.
-			// Instead, interpret the C declaration
-			//	void *_Cvar_stderr = &stderr;
-			// as making _Cvar_stderr the name of a GOT entry
-			// for stderr. This is separate from the usual GOT entry,
-			// just in case the C code assigns to the variable,
-			// and of course it only works for single pointers,
-			// but we only need to support cgo and that's all it needs.
-			ld.Adddynsym(ctxt, targ)
-
-			got := ctxt.Syms.Lookup(".got", 0)
-			s.Type = got.Type
-			s.Attr |= sym.AttrSubSymbol
-			s.Outer = got
-			s.Sub = got.Sub
-			got.Sub = s
-			s.Value = got.Size
-			got.AddUint64(ctxt.Arch, 0)
-			ctxt.Syms.Lookup(".linkedit.got", 0).AddUint32(ctxt.Arch, uint32(targ.Dynid))
-			r.Type = objabi.ElfRelocOffset // ignore during relocsym
-			return true
-		}
-	}
-
-	return false
-}
-
-func elfreloc1(ctxt *ld.Link, r *sym.Reloc, sectoff int64) bool {
-	ctxt.Out.Write64(uint64(sectoff))
-
-	elfsym := r.Xsym.ElfsymForReloc()
-	switch r.Type {
-	default:
-		return false
-	case objabi.R_ADDR:
-		if r.Siz == 4 {
-			ctxt.Out.Write64(uint64(elf.R_X86_64_32) | uint64(elfsym)<<32)
-		} else if r.Siz == 8 {
-			ctxt.Out.Write64(uint64(elf.R_X86_64_64) | uint64(elfsym)<<32)
-		} else {
-			return false
-		}
-	case objabi.R_TLS_LE:
-		if r.Siz == 4 {
-			ctxt.Out.Write64(uint64(elf.R_X86_64_TPOFF32) | uint64(elfsym)<<32)
-		} else {
-			return false
-		}
-	case objabi.R_TLS_IE:
-		if r.Siz == 4 {
-			ctxt.Out.Write64(uint64(elf.R_X86_64_GOTTPOFF) | uint64(elfsym)<<32)
-		} else {
-			return false
-		}
-	case objabi.R_CALL:
-		if r.Siz == 4 {
-			if r.Xsym.Type == sym.SDYNIMPORT {
-				if ctxt.DynlinkingGo() {
-					ctxt.Out.Write64(uint64(elf.R_X86_64_PLT32) | uint64(elfsym)<<32)
-				} else {
-					ctxt.Out.Write64(uint64(elf.R_X86_64_GOTPCREL) | uint64(elfsym)<<32)
-				}
-			} else {
-				ctxt.Out.Write64(uint64(elf.R_X86_64_PC32) | uint64(elfsym)<<32)
-			}
-		} else {
-			return false
-		}
-	case objabi.R_PCREL:
-		if r.Siz == 4 {
-			if r.Xsym.Type == sym.SDYNIMPORT && r.Xsym.ElfType() == elf.STT_FUNC {
-				ctxt.Out.Write64(uint64(elf.R_X86_64_PLT32) | uint64(elfsym)<<32)
-			} else {
-				ctxt.Out.Write64(uint64(elf.R_X86_64_PC32) | uint64(elfsym)<<32)
-			}
-		} else {
-			return false
-		}
-	case objabi.R_GOTPCREL:
-		if r.Siz == 4 {
-			ctxt.Out.Write64(uint64(elf.R_X86_64_GOTPCREL) | uint64(elfsym)<<32)
-		} else {
-			return false
-		}
-	}
-
-	ctxt.Out.Write64(uint64(r.Xadd))
-	return true
-}
-
-func machoreloc1(arch *sys.Arch, out *ld.OutBuf, s *sym.Symbol, r *sym.Reloc, sectoff int64) bool {
-	var v uint32
-
-	rs := r.Xsym
-
-	if rs.Type == sym.SHOSTOBJ || r.Type == objabi.R_PCREL || r.Type == objabi.R_GOTPCREL || r.Type == objabi.R_CALL {
-		if rs.Dynid < 0 {
-			ld.Errorf(s, "reloc %d (%s) to non-macho symbol %s type=%d (%s)", r.Type, sym.RelocName(arch, r.Type), rs.Name, rs.Type, rs.Type)
-			return false
-		}
-
-		v = uint32(rs.Dynid)
-		v |= 1 << 27 // external relocation
-	} else {
-		v = uint32(rs.Sect.Extnum)
-		if v == 0 {
-			ld.Errorf(s, "reloc %d (%s) to symbol %s in non-macho section %s type=%d (%s)", r.Type, sym.RelocName(arch, r.Type), rs.Name, rs.Sect.Name, rs.Type, rs.Type)
-			return false
-		}
-	}
-
-	switch r.Type {
-	default:
-		return false
-
-	case objabi.R_ADDR:
-		v |= ld.MACHO_X86_64_RELOC_UNSIGNED << 28
-
-	case objabi.R_CALL:
-		v |= 1 << 24 // pc-relative bit
-		v |= ld.MACHO_X86_64_RELOC_BRANCH << 28
-
-		// NOTE: Only works with 'external' relocation. Forced above.
-	case objabi.R_PCREL:
-		v |= 1 << 24 // pc-relative bit
-		v |= ld.MACHO_X86_64_RELOC_SIGNED << 28
-	case objabi.R_GOTPCREL:
-		v |= 1 << 24 // pc-relative bit
-		v |= ld.MACHO_X86_64_RELOC_GOT_LOAD << 28
-	}
-
-	switch r.Siz {
-	default:
-		return false
-
-	case 1:
-		v |= 0 << 25
-
-	case 2:
-		v |= 1 << 25
-
-	case 4:
-		v |= 2 << 25
-
-	case 8:
-		v |= 3 << 25
-	}
-
-	out.Write32(uint32(sectoff))
-	out.Write32(v)
-	return true
-}
-
-func pereloc1(arch *sys.Arch, out *ld.OutBuf, s *sym.Symbol, r *sym.Reloc, sectoff int64) bool {
-	var v uint32
-
-	rs := r.Xsym
-
-	if rs.Dynid < 0 {
-		ld.Errorf(s, "reloc %d (%s) to non-coff symbol %s type=%d (%s)", r.Type, sym.RelocName(arch, r.Type), rs.Name, rs.Type, rs.Type)
-		return false
-	}
-
-	out.Write32(uint32(sectoff))
-	out.Write32(uint32(rs.Dynid))
-
-	switch r.Type {
-	default:
-		return false
-
-	case objabi.R_DWARFSECREF:
-		v = ld.IMAGE_REL_AMD64_SECREL
-
-	case objabi.R_ADDR:
-		if r.Siz == 8 {
-			v = ld.IMAGE_REL_AMD64_ADDR64
-		} else {
-			v = ld.IMAGE_REL_AMD64_ADDR32
-		}
-
-	case objabi.R_CALL,
-		objabi.R_PCREL:
-		v = ld.IMAGE_REL_AMD64_REL32
-	}
-
-	out.Write16(uint16(v))
-
-	return true
-}
-
-func archreloc(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, val int64) (int64, bool) {
-	return val, false
-}
-
-func archrelocvariant(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, t int64) int64 {
-	log.Fatalf("unexpected relocation variant")
-	return t
-}
-
-func elfsetupplt(ctxt *ld.Link) {
-	plt := ctxt.Syms.Lookup(".plt", 0)
-	got := ctxt.Syms.Lookup(".got.plt", 0)
-	if plt.Size == 0 {
-		// pushq got+8(IP)
-		plt.AddUint8(0xff)
-
-		plt.AddUint8(0x35)
-		plt.AddPCRelPlus(ctxt.Arch, got, 8)
-
-		// jmpq got+16(IP)
-		plt.AddUint8(0xff)
-
-		plt.AddUint8(0x25)
-		plt.AddPCRelPlus(ctxt.Arch, got, 16)
-
-		// nopl 0(AX)
-		plt.AddUint32(ctxt.Arch, 0x00401f0f)
-
-		// assume got->size == 0 too
-		got.AddAddrPlus(ctxt.Arch, ctxt.Syms.Lookup(".dynamic", 0), 0)
-
-		got.AddUint64(ctxt.Arch, 0)
-		got.AddUint64(ctxt.Arch, 0)
-	}
-}
-
-func addpltsym(ctxt *ld.Link, s *sym.Symbol) {
-	if s.Plt() >= 0 {
-		return
-	}
-
-	ld.Adddynsym(ctxt, s)
-
-	if ctxt.IsELF {
-		plt := ctxt.Syms.Lookup(".plt", 0)
-		got := ctxt.Syms.Lookup(".got.plt", 0)
-		rela := ctxt.Syms.Lookup(".rela.plt", 0)
-		if plt.Size == 0 {
-			elfsetupplt(ctxt)
-		}
-
-		// jmpq *got+size(IP)
-		plt.AddUint8(0xff)
-
-		plt.AddUint8(0x25)
-		plt.AddPCRelPlus(ctxt.Arch, got, got.Size)
-
-		// add to got: pointer to current pos in plt
-		got.AddAddrPlus(ctxt.Arch, plt, plt.Size)
-
-		// pushq $x
-		plt.AddUint8(0x68)
-
-		plt.AddUint32(ctxt.Arch, uint32((got.Size-24-8)/8))
-
-		// jmpq .plt
-		plt.AddUint8(0xe9)
-
-		plt.AddUint32(ctxt.Arch, uint32(-(plt.Size + 4)))
-
-		// rela
-		rela.AddAddrPlus(ctxt.Arch, got, got.Size-8)
-
-		rela.AddUint64(ctxt.Arch, ld.ELF64_R_INFO(uint32(s.Dynid), uint32(elf.R_X86_64_JMP_SLOT)))
-		rela.AddUint64(ctxt.Arch, 0)
-
-		s.SetPlt(int32(plt.Size - 16))
-	} else if ctxt.HeadType == objabi.Hdarwin {
-		// To do lazy symbol lookup right, we're supposed
-		// to tell the dynamic loader which library each
-		// symbol comes from and format the link info
-		// section just so. I'm too lazy (ha!) to do that
-		// so for now we'll just use non-lazy pointers,
-		// which don't need to be told which library to use.
-		//
-		// https://networkpx.blogspot.com/2009/09/about-lcdyldinfoonly-command.html
-		// has details about what we're avoiding.
-
-		addgotsym(ctxt, s)
-		plt := ctxt.Syms.Lookup(".plt", 0)
-
-		ctxt.Syms.Lookup(".linkedit.plt", 0).AddUint32(ctxt.Arch, uint32(s.Dynid))
-
-		// jmpq *got+size(IP)
-		s.SetPlt(int32(plt.Size))
-
-		plt.AddUint8(0xff)
-		plt.AddUint8(0x25)
-		plt.AddPCRelPlus(ctxt.Arch, ctxt.Syms.Lookup(".got", 0), int64(s.Got()))
-	} else {
-		ld.Errorf(s, "addpltsym: unsupported binary format")
-	}
-}
-
-func addgotsym(ctxt *ld.Link, s *sym.Symbol) {
-	if s.Got() >= 0 {
-		return
-	}
-
-	ld.Adddynsym(ctxt, s)
-	got := ctxt.Syms.Lookup(".got", 0)
-	s.SetGot(int32(got.Size))
-	got.AddUint64(ctxt.Arch, 0)
-
-	if ctxt.IsELF {
-		rela := ctxt.Syms.Lookup(".rela", 0)
-		rela.AddAddrPlus(ctxt.Arch, got, int64(s.Got()))
-		rela.AddUint64(ctxt.Arch, ld.ELF64_R_INFO(uint32(s.Dynid), uint32(elf.R_X86_64_GLOB_DAT)))
-		rela.AddUint64(ctxt.Arch, 0)
-	} else if ctxt.HeadType == objabi.Hdarwin {
-		ctxt.Syms.Lookup(".linkedit.got", 0).AddUint32(ctxt.Arch, uint32(s.Dynid))
-	} else {
-		ld.Errorf(s, "addgotsym: unsupported binary format")
-	}
-}
-
-func asmb(ctxt *ld.Link) {
-	if ctxt.IsELF {
-		ld.Asmbelfsetup()
-	}
-
-	sect := ld.Segtext.Sections[0]
-	ctxt.Out.SeekSet(int64(sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff))
-	// 0xCC is INT $3 - breakpoint instruction
-	ld.CodeblkPad(ctxt, int64(sect.Vaddr), int64(sect.Length), []byte{0xCC})
-	for _, sect = range ld.Segtext.Sections[1:] {
-		ctxt.Out.SeekSet(int64(sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff))
-		ld.Datblk(ctxt, int64(sect.Vaddr), int64(sect.Length))
-	}
-
-	if ld.Segrodata.Filelen > 0 {
-		ctxt.Out.SeekSet(int64(ld.Segrodata.Fileoff))
-		ld.Datblk(ctxt, int64(ld.Segrodata.Vaddr), int64(ld.Segrodata.Filelen))
-	}
-	if ld.Segrelrodata.Filelen > 0 {
-		ctxt.Out.SeekSet(int64(ld.Segrelrodata.Fileoff))
-		ld.Datblk(ctxt, int64(ld.Segrelrodata.Vaddr), int64(ld.Segrelrodata.Filelen))
-	}
-
-	ctxt.Out.SeekSet(int64(ld.Segdata.Fileoff))
-	ld.Datblk(ctxt, int64(ld.Segdata.Vaddr), int64(ld.Segdata.Filelen))
-
-	ctxt.Out.SeekSet(int64(ld.Segdwarf.Fileoff))
-	ld.Dwarfblk(ctxt, int64(ld.Segdwarf.Vaddr), int64(ld.Segdwarf.Filelen))
-}
-
-func asmb2(ctxt *ld.Link) {
-	machlink := int64(0)
-	if ctxt.HeadType == objabi.Hdarwin {
-		machlink = ld.Domacholink(ctxt)
-	}
-
-	switch ctxt.HeadType {
-	default:
-		ld.Errorf(nil, "unknown header type %v", ctxt.HeadType)
-		fallthrough
-
-	case objabi.Hplan9:
-		break
-
-	case objabi.Hdarwin:
-		ld.Flag8 = true /* 64-bit addresses */
-
-	case objabi.Hlinux,
-		objabi.Hfreebsd,
-		objabi.Hnetbsd,
-		objabi.Hopenbsd,
-		objabi.Hdragonfly,
-		objabi.Hsolaris:
-		ld.Flag8 = true /* 64-bit addresses */
-
-	case objabi.Hwindows:
-		break
-	}
-
-	ld.Symsize = 0
-	ld.Spsize = 0
-	ld.Lcsize = 0
-	symo := int64(0)
-	if !*ld.FlagS {
-		switch ctxt.HeadType {
-		default:
-		case objabi.Hplan9:
-			*ld.FlagS = true
-			symo = int64(ld.Segdata.Fileoff + ld.Segdata.Filelen)
-
-		case objabi.Hdarwin:
-			symo = int64(ld.Segdwarf.Fileoff + uint64(ld.Rnd(int64(ld.Segdwarf.Filelen), int64(*ld.FlagRound))) + uint64(machlink))
-
-		case objabi.Hlinux,
-			objabi.Hfreebsd,
-			objabi.Hnetbsd,
-			objabi.Hopenbsd,
-			objabi.Hdragonfly,
-			objabi.Hsolaris:
-			symo = int64(ld.Segdwarf.Fileoff + ld.Segdwarf.Filelen)
-			symo = ld.Rnd(symo, int64(*ld.FlagRound))
-
-		case objabi.Hwindows:
-			symo = int64(ld.Segdwarf.Fileoff + ld.Segdwarf.Filelen)
-			symo = ld.Rnd(symo, ld.PEFILEALIGN)
-		}
-
-		ctxt.Out.SeekSet(symo)
-		switch ctxt.HeadType {
-		default:
-			if ctxt.IsELF {
-				ctxt.Out.SeekSet(symo)
-				ld.Asmelfsym(ctxt)
-				ctxt.Out.Flush()
-				ctxt.Out.Write(ld.Elfstrdat)
-
-				if ctxt.LinkMode == ld.LinkExternal {
-					ld.Elfemitreloc(ctxt)
-				}
-			}
-
-		case objabi.Hplan9:
-			ld.Asmplan9sym(ctxt)
-			ctxt.Out.Flush()
-
-			sym := ctxt.Syms.Lookup("pclntab", 0)
-			if sym != nil {
-				ld.Lcsize = int32(len(sym.P))
-				ctxt.Out.Write(sym.P)
-				ctxt.Out.Flush()
-			}
-
-		case objabi.Hwindows:
-			// Do nothing
-
-		case objabi.Hdarwin:
-			if ctxt.LinkMode == ld.LinkExternal {
-				ld.Machoemitreloc(ctxt)
-			}
-		}
-	}
-
-	ctxt.Out.SeekSet(0)
-	switch ctxt.HeadType {
-	default:
-	case objabi.Hplan9: /* plan9 */
-		magic := int32(4*26*26 + 7)
-
-		magic |= 0x00008000                           /* fat header */
-		ctxt.Out.Write32b(uint32(magic))              /* magic */
-		ctxt.Out.Write32b(uint32(ld.Segtext.Filelen)) /* sizes */
-		ctxt.Out.Write32b(uint32(ld.Segdata.Filelen))
-		ctxt.Out.Write32b(uint32(ld.Segdata.Length - ld.Segdata.Filelen))
-		ctxt.Out.Write32b(uint32(ld.Symsize)) /* nsyms */
-		vl := ld.Entryvalue(ctxt)
-		ctxt.Out.Write32b(PADDR(uint32(vl))) /* va of entry */
-		ctxt.Out.Write32b(uint32(ld.Spsize)) /* sp offsets */
-		ctxt.Out.Write32b(uint32(ld.Lcsize)) /* line offsets */
-		ctxt.Out.Write64b(uint64(vl))        /* va of entry */
-
-	case objabi.Hdarwin:
-		ld.Asmbmacho(ctxt)
-
-	case objabi.Hlinux,
-		objabi.Hfreebsd,
-		objabi.Hnetbsd,
-		objabi.Hopenbsd,
-		objabi.Hdragonfly,
-		objabi.Hsolaris:
-		ld.Asmbelf(ctxt, symo)
-
-	case objabi.Hwindows:
-		ld.Asmbpe(ctxt)
-	}
-
-	ctxt.Out.Flush()
-}
-
-func tlsIEtoLE(s *sym.Symbol, off, size int) {
-	// Transform the PC-relative instruction into a constant load.
-	// That is,
-	//
-	//	MOVQ X(IP), REG  ->  MOVQ $Y, REG
-	//
-	// To determine the instruction and register, we study the op codes.
-	// Consult an AMD64 instruction encoding guide to decipher this.
-	if off < 3 {
-		log.Fatal("R_X86_64_GOTTPOFF reloc not preceded by MOVQ or ADDQ instruction")
-	}
-	op := s.P[off-3 : off]
-	reg := op[2] >> 3
-
-	if op[1] == 0x8b || reg == 4 {
-		// MOVQ
-		if op[0] == 0x4c {
-			op[0] = 0x49
-		} else if size == 4 && op[0] == 0x44 {
-			op[0] = 0x41
-		}
-		if op[1] == 0x8b {
-			op[1] = 0xc7
-		} else {
-			op[1] = 0x81 // special case for SP
-		}
-		op[2] = 0xc0 | reg
-	} else {
-		// An alternate op is ADDQ. This is handled by GNU gold,
-		// but right now is not generated by the Go compiler:
-		//	ADDQ X(IP), REG  ->  ADDQ $Y, REG
-		// Consider adding support for it here.
-		log.Fatalf("expected TLS IE op to be MOVQ, got %v", op)
-	}
-}
diff --git a/src/cmd/oldlink/internal/amd64/l.go b/src/cmd/oldlink/internal/amd64/l.go
deleted file mode 100644
index a9afb3a..0000000
--- a/src/cmd/oldlink/internal/amd64/l.go
+++ /dev/null
@@ -1,43 +0,0 @@
-// Inferno utils/6l/l.h
-// https://bitbucket.org/inferno-os/inferno-os/src/master/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 amd64
-
-const (
-	maxAlign  = 32 // max data alignment
-	minAlign  = 1  // min data alignment
-	funcAlign = 16
-)
-
-/* Used by ../internal/ld/dwarf.go */
-const (
-	dwarfRegSP = 7
-	dwarfRegLR = 16
-)
diff --git a/src/cmd/oldlink/internal/amd64/obj.go b/src/cmd/oldlink/internal/amd64/obj.go
deleted file mode 100644
index ab85ab2..0000000
--- a/src/cmd/oldlink/internal/amd64/obj.go
+++ /dev/null
@@ -1,117 +0,0 @@
-// Inferno utils/6l/obj.c
-// https://bitbucket.org/inferno-os/inferno-os/src/master/utils/6l/obj.c
-//
-//	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 amd64
-
-import (
-	"cmd/internal/objabi"
-	"cmd/internal/sys"
-	"cmd/oldlink/internal/ld"
-)
-
-func Init() (*sys.Arch, ld.Arch) {
-	arch := sys.ArchAMD64
-
-	theArch := ld.Arch{
-		Funcalign:  funcAlign,
-		Maxalign:   maxAlign,
-		Minalign:   minAlign,
-		Dwarfregsp: dwarfRegSP,
-		Dwarfreglr: dwarfRegLR,
-
-		Adddynrel:        adddynrel,
-		Archinit:         archinit,
-		Archreloc:        archreloc,
-		Archrelocvariant: archrelocvariant,
-		Asmb:             asmb,
-		Asmb2:            asmb2,
-		Elfreloc1:        elfreloc1,
-		Elfsetupplt:      elfsetupplt,
-		Gentext:          gentext,
-		Machoreloc1:      machoreloc1,
-		PEreloc1:         pereloc1,
-		TLSIEtoLE:        tlsIEtoLE,
-
-		Linuxdynld:     "/lib64/ld-linux-x86-64.so.2",
-		Freebsddynld:   "/libexec/ld-elf.so.1",
-		Openbsddynld:   "/usr/libexec/ld.so",
-		Netbsddynld:    "/libexec/ld.elf_so",
-		Dragonflydynld: "/usr/libexec/ld-elf.so.2",
-		Solarisdynld:   "/lib/amd64/ld.so.1",
-	}
-
-	return arch, theArch
-}
-
-func archinit(ctxt *ld.Link) {
-	switch ctxt.HeadType {
-	default:
-		ld.Exitf("unknown -H option: %v", ctxt.HeadType)
-
-	case objabi.Hplan9: /* plan 9 */
-		ld.HEADR = 32 + 8
-
-		if *ld.FlagTextAddr == -1 {
-			*ld.FlagTextAddr = 0x200000 + int64(ld.HEADR)
-		}
-		if *ld.FlagRound == -1 {
-			*ld.FlagRound = 0x200000
-		}
-
-	case objabi.Hdarwin: /* apple MACH */
-		ld.HEADR = ld.INITIAL_MACHO_HEADR
-		if *ld.FlagRound == -1 {
-			*ld.FlagRound = 4096
-		}
-		if *ld.FlagTextAddr == -1 {
-			*ld.FlagTextAddr = 0x1000000 + int64(ld.HEADR)
-		}
-
-	case objabi.Hlinux, /* elf64 executable */
-		objabi.Hfreebsd,   /* freebsd */
-		objabi.Hnetbsd,    /* netbsd */
-		objabi.Hopenbsd,   /* openbsd */
-		objabi.Hdragonfly, /* dragonfly */
-		objabi.Hsolaris:   /* solaris */
-		ld.Elfinit(ctxt)
-
-		ld.HEADR = ld.ELFRESERVE
-		if *ld.FlagTextAddr == -1 {
-			*ld.FlagTextAddr = (1 << 22) + int64(ld.HEADR)
-		}
-		if *ld.FlagRound == -1 {
-			*ld.FlagRound = 4096
-		}
-
-	case objabi.Hwindows: /* PE executable */
-		// ld.HEADR, ld.FlagTextAddr, ld.FlagRound are set in ld.Peinit
-		return
-	}
-}
diff --git a/src/cmd/oldlink/internal/arm/asm.go b/src/cmd/oldlink/internal/arm/asm.go
deleted file mode 100644
index 9dc4ca0..0000000
--- a/src/cmd/oldlink/internal/arm/asm.go
+++ /dev/null
@@ -1,786 +0,0 @@
-// Inferno utils/5l/asm.c
-// https://bitbucket.org/inferno-os/inferno-os/src/master/utils/5l/asm.c
-//
-//	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 arm
-
-import (
-	"cmd/internal/objabi"
-	"cmd/internal/sys"
-	"cmd/oldlink/internal/ld"
-	"cmd/oldlink/internal/sym"
-	"debug/elf"
-	"fmt"
-	"log"
-)
-
-// This assembler:
-//
-//         .align 2
-// local.dso_init:
-//         ldr r0, .Lmoduledata
-// .Lloadfrom:
-//         ldr r0, [r0]
-//         b runtime.addmoduledata@plt
-// .align 2
-// .Lmoduledata:
-//         .word local.moduledata(GOT_PREL) + (. - (.Lloadfrom + 4))
-// assembles to:
-//
-// 00000000 <local.dso_init>:
-//    0:        e59f0004        ldr     r0, [pc, #4]    ; c <local.dso_init+0xc>
-//    4:        e5900000        ldr     r0, [r0]
-//    8:        eafffffe        b       0 <runtime.addmoduledata>
-//                      8: R_ARM_JUMP24 runtime.addmoduledata
-//    c:        00000004        .word   0x00000004
-//                      c: R_ARM_GOT_PREL       local.moduledata
-
-func gentext(ctxt *ld.Link) {
-	if !ctxt.DynlinkingGo() {
-		return
-	}
-	addmoduledata := ctxt.Syms.Lookup("runtime.addmoduledata", 0)
-	if addmoduledata.Type == sym.STEXT && ctxt.BuildMode != ld.BuildModePlugin {
-		// we're linking a module containing the runtime -> no need for
-		// an init function
-		return
-	}
-	addmoduledata.Attr |= sym.AttrReachable
-	initfunc := ctxt.Syms.Lookup("go.link.addmoduledata", 0)
-	initfunc.Type = sym.STEXT
-	initfunc.Attr |= sym.AttrLocal
-	initfunc.Attr |= sym.AttrReachable
-	o := func(op uint32) {
-		initfunc.AddUint32(ctxt.Arch, op)
-	}
-	o(0xe59f0004)
-	o(0xe08f0000)
-
-	o(0xeafffffe)
-	rel := initfunc.AddRel()
-	rel.Off = 8
-	rel.Siz = 4
-	rel.Sym = ctxt.Syms.Lookup("runtime.addmoduledata", 0)
-	rel.Type = objabi.R_CALLARM
-	rel.Add = 0xeafffffe // vomit
-
-	o(0x00000000)
-	rel = initfunc.AddRel()
-	rel.Off = 12
-	rel.Siz = 4
-	rel.Sym = ctxt.Moduledata
-	rel.Type = objabi.R_PCREL
-	rel.Add = 4
-
-	if ctxt.BuildMode == ld.BuildModePlugin {
-		ctxt.Textp = append(ctxt.Textp, addmoduledata)
-	}
-	ctxt.Textp = append(ctxt.Textp, initfunc)
-	initarray_entry := ctxt.Syms.Lookup("go.link.addmoduledatainit", 0)
-	initarray_entry.Attr |= sym.AttrReachable
-	initarray_entry.Attr |= sym.AttrLocal
-	initarray_entry.Type = sym.SINITARR
-	initarray_entry.AddAddr(ctxt.Arch, initfunc)
-}
-
-// Preserve highest 8 bits of a, and do addition to lower 24-bit
-// of a and b; used to adjust ARM branch instruction's target
-func braddoff(a int32, b int32) int32 {
-	return int32((uint32(a))&0xff000000 | 0x00ffffff&uint32(a+b))
-}
-
-func adddynrel(ctxt *ld.Link, s *sym.Symbol, r *sym.Reloc) bool {
-	targ := r.Sym
-
-	switch r.Type {
-	default:
-		if r.Type >= objabi.ElfRelocOffset {
-			ld.Errorf(s, "unexpected relocation type %d (%s)", r.Type, sym.RelocName(ctxt.Arch, r.Type))
-			return false
-		}
-
-		// Handle relocations found in ELF object files.
-	case objabi.ElfRelocOffset + objabi.RelocType(elf.R_ARM_PLT32):
-		r.Type = objabi.R_CALLARM
-
-		if targ.Type == sym.SDYNIMPORT {
-			addpltsym(ctxt, targ)
-			r.Sym = ctxt.Syms.Lookup(".plt", 0)
-			r.Add = int64(braddoff(int32(r.Add), targ.Plt()/4))
-		}
-
-		return true
-
-	case objabi.ElfRelocOffset + objabi.RelocType(elf.R_ARM_THM_PC22): // R_ARM_THM_CALL
-		ld.Exitf("R_ARM_THM_CALL, are you using -marm?")
-		return false
-
-	case objabi.ElfRelocOffset + objabi.RelocType(elf.R_ARM_GOT32): // R_ARM_GOT_BREL
-		if targ.Type != sym.SDYNIMPORT {
-			addgotsyminternal(ctxt, targ)
-		} else {
-			addgotsym(ctxt, targ)
-		}
-
-		r.Type = objabi.R_CONST // write r->add during relocsym
-		r.Sym = nil
-		r.Add += int64(targ.Got())
-		return true
-
-	case objabi.ElfRelocOffset + objabi.RelocType(elf.R_ARM_GOT_PREL): // GOT(nil) + A - nil
-		if targ.Type != sym.SDYNIMPORT {
-			addgotsyminternal(ctxt, targ)
-		} else {
-			addgotsym(ctxt, targ)
-		}
-
-		r.Type = objabi.R_PCREL
-		r.Sym = ctxt.Syms.Lookup(".got", 0)
-		r.Add += int64(targ.Got()) + 4
-		return true
-
-	case objabi.ElfRelocOffset + objabi.RelocType(elf.R_ARM_GOTOFF): // R_ARM_GOTOFF32
-		r.Type = objabi.R_GOTOFF
-
-		return true
-
-	case objabi.ElfRelocOffset + objabi.RelocType(elf.R_ARM_GOTPC): // R_ARM_BASE_PREL
-		r.Type = objabi.R_PCREL
-
-		r.Sym = ctxt.Syms.Lookup(".got", 0)
-		r.Add += 4
-		return true
-
-	case objabi.ElfRelocOffset + objabi.RelocType(elf.R_ARM_CALL):
-		r.Type = objabi.R_CALLARM
-		if targ.Type == sym.SDYNIMPORT {
-			addpltsym(ctxt, targ)
-			r.Sym = ctxt.Syms.Lookup(".plt", 0)
-			r.Add = int64(braddoff(int32(r.Add), targ.Plt()/4))
-		}
-
-		return true
-
-	case objabi.ElfRelocOffset + objabi.RelocType(elf.R_ARM_REL32): // R_ARM_REL32
-		r.Type = objabi.R_PCREL
-
-		r.Add += 4
-		return true
-
-	case objabi.ElfRelocOffset + objabi.RelocType(elf.R_ARM_ABS32):
-		if targ.Type == sym.SDYNIMPORT {
-			ld.Errorf(s, "unexpected R_ARM_ABS32 relocation for dynamic symbol %s", targ.Name)
-		}
-		r.Type = objabi.R_ADDR
-		return true
-
-		// we can just ignore this, because we are targeting ARM V5+ anyway
-	case objabi.ElfRelocOffset + objabi.RelocType(elf.R_ARM_V4BX):
-		if r.Sym != nil {
-			// R_ARM_V4BX is ABS relocation, so this symbol is a dummy symbol, ignore it
-			r.Sym.Type = 0
-		}
-
-		r.Sym = nil
-		return true
-
-	case objabi.ElfRelocOffset + objabi.RelocType(elf.R_ARM_PC24),
-		objabi.ElfRelocOffset + objabi.RelocType(elf.R_ARM_JUMP24):
-		r.Type = objabi.R_CALLARM
-		if targ.Type == sym.SDYNIMPORT {
-			addpltsym(ctxt, targ)
-			r.Sym = ctxt.Syms.Lookup(".plt", 0)
-			r.Add = int64(braddoff(int32(r.Add), targ.Plt()/4))
-		}
-
-		return true
-	}
-
-	// Handle references to ELF symbols from our own object files.
-	if targ.Type != sym.SDYNIMPORT {
-		return true
-	}
-
-	switch r.Type {
-	case objabi.R_CALLARM:
-		if ctxt.LinkMode == ld.LinkExternal {
-			// External linker will do this relocation.
-			return true
-		}
-		addpltsym(ctxt, targ)
-		r.Sym = ctxt.Syms.Lookup(".plt", 0)
-		r.Add = int64(targ.Plt())
-		return true
-
-	case objabi.R_ADDR:
-		if s.Type != sym.SDATA {
-			break
-		}
-		if ctxt.IsELF {
-			ld.Adddynsym(ctxt, targ)
-			rel := ctxt.Syms.Lookup(".rel", 0)
-			rel.AddAddrPlus(ctxt.Arch, s, int64(r.Off))
-			rel.AddUint32(ctxt.Arch, ld.ELF32_R_INFO(uint32(targ.Dynid), uint32(elf.R_ARM_GLOB_DAT))) // we need a nil + A dynamic reloc
-			r.Type = objabi.R_CONST                                                                   // write r->add during relocsym
-			r.Sym = nil
-			return true
-		}
-	}
-
-	return false
-}
-
-func elfreloc1(ctxt *ld.Link, r *sym.Reloc, sectoff int64) bool {
-	ctxt.Out.Write32(uint32(sectoff))
-
-	elfsym := r.Xsym.ElfsymForReloc()
-	switch r.Type {
-	default:
-		return false
-	case objabi.R_ADDR:
-		if r.Siz == 4 {
-			ctxt.Out.Write32(uint32(elf.R_ARM_ABS32) | uint32(elfsym)<<8)
-		} else {
-			return false
-		}
-	case objabi.R_PCREL:
-		if r.Siz == 4 {
-			ctxt.Out.Write32(uint32(elf.R_ARM_REL32) | uint32(elfsym)<<8)
-		} else {
-			return false
-		}
-	case objabi.R_CALLARM:
-		if r.Siz == 4 {
-			if r.Add&0xff000000 == 0xeb000000 { // BL
-				ctxt.Out.Write32(uint32(elf.R_ARM_CALL) | uint32(elfsym)<<8)
-			} else {
-				ctxt.Out.Write32(uint32(elf.R_ARM_JUMP24) | uint32(elfsym)<<8)
-			}
-		} else {
-			return false
-		}
-	case objabi.R_TLS_LE:
-		ctxt.Out.Write32(uint32(elf.R_ARM_TLS_LE32) | uint32(elfsym)<<8)
-	case objabi.R_TLS_IE:
-		ctxt.Out.Write32(uint32(elf.R_ARM_TLS_IE32) | uint32(elfsym)<<8)
-	case objabi.R_GOTPCREL:
-		if r.Siz == 4 {
-			ctxt.Out.Write32(uint32(elf.R_ARM_GOT_PREL) | uint32(elfsym)<<8)
-		} else {
-			return false
-		}
-	}
-
-	return true
-}
-
-func elfsetupplt(ctxt *ld.Link) {
-	plt := ctxt.Syms.Lookup(".plt", 0)
-	got := ctxt.Syms.Lookup(".got.plt", 0)
-	if plt.Size == 0 {
-		// str lr, [sp, #-4]!
-		plt.AddUint32(ctxt.Arch, 0xe52de004)
-
-		// ldr lr, [pc, #4]
-		plt.AddUint32(ctxt.Arch, 0xe59fe004)
-
-		// add lr, pc, lr
-		plt.AddUint32(ctxt.Arch, 0xe08fe00e)
-
-		// ldr pc, [lr, #8]!
-		plt.AddUint32(ctxt.Arch, 0xe5bef008)
-
-		// .word &GLOBAL_OFFSET_TABLE[0] - .
-		plt.AddPCRelPlus(ctxt.Arch, got, 4)
-
-		// the first .plt entry requires 3 .plt.got entries
-		got.AddUint32(ctxt.Arch, 0)
-
-		got.AddUint32(ctxt.Arch, 0)
-		got.AddUint32(ctxt.Arch, 0)
-	}
-}
-
-func machoreloc1(arch *sys.Arch, out *ld.OutBuf, s *sym.Symbol, r *sym.Reloc, sectoff int64) bool {
-	return false
-}
-
-func pereloc1(arch *sys.Arch, out *ld.OutBuf, s *sym.Symbol, r *sym.Reloc, sectoff int64) bool {
-	rs := r.Xsym
-
-	if rs.Dynid < 0 {
-		ld.Errorf(s, "reloc %d (%s) to non-coff symbol %s type=%d (%s)", r.Type, sym.RelocName(arch, r.Type), rs.Name, rs.Type, rs.Type)
-		return false
-	}
-
-	out.Write32(uint32(sectoff))
-	out.Write32(uint32(rs.Dynid))
-
-	var v uint32
-	switch r.Type {
-	default:
-		// unsupported relocation type
-		return false
-
-	case objabi.R_DWARFSECREF:
-		v = ld.IMAGE_REL_ARM_SECREL
-
-	case objabi.R_ADDR:
-		v = ld.IMAGE_REL_ARM_ADDR32
-	}
-
-	out.Write16(uint16(v))
-
-	return true
-}
-
-// sign extend a 24-bit integer
-func signext24(x int64) int32 {
-	return (int32(x) << 8) >> 8
-}
-
-// encode an immediate in ARM's imm12 format. copied from ../../../internal/obj/arm/asm5.go
-func immrot(v uint32) uint32 {
-	for i := 0; i < 16; i++ {
-		if v&^0xff == 0 {
-			return uint32(i<<8) | v | 1<<25
-		}
-		v = v<<2 | v>>30
-	}
-	return 0
-}
-
-// Convert the direct jump relocation r to refer to a trampoline if the target is too far
-func trampoline(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol) {
-	switch r.Type {
-	case objabi.R_CALLARM:
-		// r.Add is the instruction
-		// low 24-bit encodes the target address
-		t := (ld.Symaddr(r.Sym) + int64(signext24(r.Add&0xffffff)*4) - (s.Value + int64(r.Off))) / 4
-		if t > 0x7fffff || t < -0x800000 || (*ld.FlagDebugTramp > 1 && s.File != r.Sym.File) {
-			// direct call too far, need to insert trampoline.
-			// look up existing trampolines first. if we found one within the range
-			// of direct call, we can reuse it. otherwise create a new one.
-			offset := (signext24(r.Add&0xffffff) + 2) * 4
-			var tramp *sym.Symbol
-			for i := 0; ; i++ {
-				name := r.Sym.Name + fmt.Sprintf("%+d-tramp%d", offset, i)
-				tramp = ctxt.Syms.Lookup(name, int(r.Sym.Version))
-				if tramp.Type == sym.SDYNIMPORT {
-					// don't reuse trampoline defined in other module
-					continue
-				}
-				if tramp.Value == 0 {
-					// either the trampoline does not exist -- we need to create one,
-					// or found one the address which is not assigned -- this will be
-					// laid down immediately after the current function. use this one.
-					break
-				}
-
-				t = (ld.Symaddr(tramp) - 8 - (s.Value + int64(r.Off))) / 4
-				if t >= -0x800000 && t < 0x7fffff {
-					// found an existing trampoline that is not too far
-					// we can just use it
-					break
-				}
-			}
-			if tramp.Type == 0 {
-				// trampoline does not exist, create one
-				ctxt.AddTramp(tramp)
-				if ctxt.DynlinkingGo() {
-					if immrot(uint32(offset)) == 0 {
-						ld.Errorf(s, "odd offset in dynlink direct call: %v+%d", r.Sym, offset)
-					}
-					gentrampdyn(ctxt.Arch, tramp, r.Sym, int64(offset))
-				} else if ctxt.BuildMode == ld.BuildModeCArchive || ctxt.BuildMode == ld.BuildModeCShared || ctxt.BuildMode == ld.BuildModePIE {
-					gentramppic(ctxt.Arch, tramp, r.Sym, int64(offset))
-				} else {
-					gentramp(ctxt.Arch, ctxt.LinkMode, tramp, r.Sym, int64(offset))
-				}
-			}
-			// modify reloc to point to tramp, which will be resolved later
-			r.Sym = tramp
-			r.Add = r.Add&0xff000000 | 0xfffffe // clear the offset embedded in the instruction
-			r.Done = false
-		}
-	default:
-		ld.Errorf(s, "trampoline called with non-jump reloc: %d (%s)", r.Type, sym.RelocName(ctxt.Arch, r.Type))
-	}
-}
-
-// generate a trampoline to target+offset
-func gentramp(arch *sys.Arch, linkmode ld.LinkMode, tramp, target *sym.Symbol, offset int64) {
-	tramp.Size = 12 // 3 instructions
-	tramp.P = make([]byte, tramp.Size)
-	t := ld.Symaddr(target) + offset
-	o1 := uint32(0xe5900000 | 11<<12 | 15<<16) // MOVW (R15), R11 // R15 is actual pc + 8
-	o2 := uint32(0xe12fff10 | 11)              // JMP  (R11)
-	o3 := uint32(t)                            // WORD $target
-	arch.ByteOrder.PutUint32(tramp.P, o1)
-	arch.ByteOrder.PutUint32(tramp.P[4:], o2)
-	arch.ByteOrder.PutUint32(tramp.P[8:], o3)
-
-	if linkmode == ld.LinkExternal {
-		r := tramp.AddRel()
-		r.Off = 8
-		r.Type = objabi.R_ADDR
-		r.Siz = 4
-		r.Sym = target
-		r.Add = offset
-	}
-}
-
-// generate a trampoline to target+offset in position independent code
-func gentramppic(arch *sys.Arch, tramp, target *sym.Symbol, offset int64) {
-	tramp.Size = 16 // 4 instructions
-	tramp.P = make([]byte, tramp.Size)
-	o1 := uint32(0xe5900000 | 11<<12 | 15<<16 | 4)  // MOVW 4(R15), R11 // R15 is actual pc + 8
-	o2 := uint32(0xe0800000 | 11<<12 | 15<<16 | 11) // ADD R15, R11, R11
-	o3 := uint32(0xe12fff10 | 11)                   // JMP  (R11)
-	o4 := uint32(0)                                 // WORD $(target-pc) // filled in with relocation
-	arch.ByteOrder.PutUint32(tramp.P, o1)
-	arch.ByteOrder.PutUint32(tramp.P[4:], o2)
-	arch.ByteOrder.PutUint32(tramp.P[8:], o3)
-	arch.ByteOrder.PutUint32(tramp.P[12:], o4)
-
-	r := tramp.AddRel()
-	r.Off = 12
-	r.Type = objabi.R_PCREL
-	r.Siz = 4
-	r.Sym = target
-	r.Add = offset + 4
-}
-
-// generate a trampoline to target+offset in dynlink mode (using GOT)
-func gentrampdyn(arch *sys.Arch, tramp, target *sym.Symbol, offset int64) {
-	tramp.Size = 20                                 // 5 instructions
-	o1 := uint32(0xe5900000 | 11<<12 | 15<<16 | 8)  // MOVW 8(R15), R11 // R15 is actual pc + 8
-	o2 := uint32(0xe0800000 | 11<<12 | 15<<16 | 11) // ADD R15, R11, R11
-	o3 := uint32(0xe5900000 | 11<<12 | 11<<16)      // MOVW (R11), R11
-	o4 := uint32(0xe12fff10 | 11)                   // JMP  (R11)
-	o5 := uint32(0)                                 // WORD $target@GOT // filled in with relocation
-	o6 := uint32(0)
-	if offset != 0 {
-		// insert an instruction to add offset
-		tramp.Size = 24 // 6 instructions
-		o6 = o5
-		o5 = o4
-		o4 = 0xe2800000 | 11<<12 | 11<<16 | immrot(uint32(offset)) // ADD $offset, R11, R11
-		o1 = uint32(0xe5900000 | 11<<12 | 15<<16 | 12)             // MOVW 12(R15), R11
-	}
-	tramp.P = make([]byte, tramp.Size)
-	arch.ByteOrder.PutUint32(tramp.P, o1)
-	arch.ByteOrder.PutUint32(tramp.P[4:], o2)
-	arch.ByteOrder.PutUint32(tramp.P[8:], o3)
-	arch.ByteOrder.PutUint32(tramp.P[12:], o4)
-	arch.ByteOrder.PutUint32(tramp.P[16:], o5)
-	if offset != 0 {
-		arch.ByteOrder.PutUint32(tramp.P[20:], o6)
-	}
-
-	r := tramp.AddRel()
-	r.Off = 16
-	r.Type = objabi.R_GOTPCREL
-	r.Siz = 4
-	r.Sym = target
-	r.Add = 8
-	if offset != 0 {
-		// increase reloc offset by 4 as we inserted an ADD instruction
-		r.Off = 20
-		r.Add = 12
-	}
-}
-
-func archreloc(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, val int64) (int64, bool) {
-	if ctxt.LinkMode == ld.LinkExternal {
-		switch r.Type {
-		case objabi.R_CALLARM:
-			r.Done = false
-
-			// set up addend for eventual relocation via outer symbol.
-			rs := r.Sym
-
-			r.Xadd = int64(signext24(r.Add & 0xffffff))
-			r.Xadd *= 4
-			for rs.Outer != nil {
-				r.Xadd += ld.Symaddr(rs) - ld.Symaddr(rs.Outer)
-				rs = rs.Outer
-			}
-
-			if rs.Type != sym.SHOSTOBJ && rs.Type != sym.SDYNIMPORT && rs.Type != sym.SUNDEFEXT && rs.Sect == nil {
-				ld.Errorf(s, "missing section for %s", rs.Name)
-			}
-			r.Xsym = rs
-
-			if r.Xadd/4 > 0x7fffff || r.Xadd/4 < -0x800000 {
-				ld.Errorf(s, "direct call too far %d", r.Xadd/4)
-			}
-
-			return int64(braddoff(int32(0xff000000&uint32(r.Add)), int32(0xffffff&uint32(r.Xadd/4)))), true
-		}
-
-		return -1, false
-	}
-
-	switch r.Type {
-	case objabi.R_CONST:
-		return r.Add, true
-	case objabi.R_GOTOFF:
-		return ld.Symaddr(r.Sym) + r.Add - ld.Symaddr(ctxt.Syms.Lookup(".got", 0)), true
-
-	// The following three arch specific relocations are only for generation of
-	// Linux/ARM ELF's PLT entry (3 assembler instruction)
-	case objabi.R_PLT0: // add ip, pc, #0xXX00000
-		if ld.Symaddr(ctxt.Syms.Lookup(".got.plt", 0)) < ld.Symaddr(ctxt.Syms.Lookup(".plt", 0)) {
-			ld.Errorf(s, ".got.plt should be placed after .plt section.")
-		}
-		return 0xe28fc600 + (0xff & (int64(uint32(ld.Symaddr(r.Sym)-(ld.Symaddr(ctxt.Syms.Lookup(".plt", 0))+int64(r.Off))+r.Add)) >> 20)), true
-	case objabi.R_PLT1: // add ip, ip, #0xYY000
-		return 0xe28cca00 + (0xff & (int64(uint32(ld.Symaddr(r.Sym)-(ld.Symaddr(ctxt.Syms.Lookup(".plt", 0))+int64(r.Off))+r.Add+4)) >> 12)), true
-	case objabi.R_PLT2: // ldr pc, [ip, #0xZZZ]!
-		return 0xe5bcf000 + (0xfff & int64(uint32(ld.Symaddr(r.Sym)-(ld.Symaddr(ctxt.Syms.Lookup(".plt", 0))+int64(r.Off))+r.Add+8))), true
-	case objabi.R_CALLARM: // bl XXXXXX or b YYYYYY
-		// r.Add is the instruction
-		// low 24-bit encodes the target address
-		t := (ld.Symaddr(r.Sym) + int64(signext24(r.Add&0xffffff)*4) - (s.Value + int64(r.Off))) / 4
-		if t > 0x7fffff || t < -0x800000 {
-			ld.Errorf(s, "direct call too far: %s %x", r.Sym.Name, t)
-		}
-		return int64(braddoff(int32(0xff000000&uint32(r.Add)), int32(0xffffff&t))), true
-	}
-
-	return val, false
-}
-
-func archrelocvariant(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, t int64) int64 {
-	log.Fatalf("unexpected relocation variant")
-	return t
-}
-
-func addpltreloc(ctxt *ld.Link, plt *sym.Symbol, got *sym.Symbol, s *sym.Symbol, typ objabi.RelocType) {
-	r := plt.AddRel()
-	r.Sym = got
-	r.Off = int32(plt.Size)
-	r.Siz = 4
-	r.Type = typ
-	r.Add = int64(s.Got()) - 8
-
-	plt.Attr |= sym.AttrReachable
-	plt.Size += 4
-	plt.Grow(plt.Size)
-}
-
-func addpltsym(ctxt *ld.Link, s *sym.Symbol) {
-	if s.Plt() >= 0 {
-		return
-	}
-
-	ld.Adddynsym(ctxt, s)
-
-	if ctxt.IsELF {
-		plt := ctxt.Syms.Lookup(".plt", 0)
-		got := ctxt.Syms.Lookup(".got.plt", 0)
-		rel := ctxt.Syms.Lookup(".rel.plt", 0)
-		if plt.Size == 0 {
-			elfsetupplt(ctxt)
-		}
-
-		// .got entry
-		s.SetGot(int32(got.Size))
-
-		// In theory, all GOT should point to the first PLT entry,
-		// Linux/ARM's dynamic linker will do that for us, but FreeBSD/ARM's
-		// dynamic linker won't, so we'd better do it ourselves.
-		got.AddAddrPlus(ctxt.Arch, plt, 0)
-
-		// .plt entry, this depends on the .got entry
-		s.SetPlt(int32(plt.Size))
-
-		addpltreloc(ctxt, plt, got, s, objabi.R_PLT0) // add lr, pc, #0xXX00000
-		addpltreloc(ctxt, plt, got, s, objabi.R_PLT1) // add lr, lr, #0xYY000
-		addpltreloc(ctxt, plt, got, s, objabi.R_PLT2) // ldr pc, [lr, #0xZZZ]!
-
-		// rel
-		rel.AddAddrPlus(ctxt.Arch, got, int64(s.Got()))
-
-		rel.AddUint32(ctxt.Arch, ld.ELF32_R_INFO(uint32(s.Dynid), uint32(elf.R_ARM_JUMP_SLOT)))
-	} else {
-		ld.Errorf(s, "addpltsym: unsupported binary format")
-	}
-}
-
-func addgotsyminternal(ctxt *ld.Link, s *sym.Symbol) {
-	if s.Got() >= 0 {
-		return
-	}
-
-	got := ctxt.Syms.Lookup(".got", 0)
-	s.SetGot(int32(got.Size))
-
-	got.AddAddrPlus(ctxt.Arch, s, 0)
-
-	if ctxt.IsELF {
-	} else {
-		ld.Errorf(s, "addgotsyminternal: unsupported binary format")
-	}
-}
-
-func addgotsym(ctxt *ld.Link, s *sym.Symbol) {
-	if s.Got() >= 0 {
-		return
-	}
-
-	ld.Adddynsym(ctxt, s)
-	got := ctxt.Syms.Lookup(".got", 0)
-	s.SetGot(int32(got.Size))
-	got.AddUint32(ctxt.Arch, 0)
-
-	if ctxt.IsELF {
-		rel := ctxt.Syms.Lookup(".rel", 0)
-		rel.AddAddrPlus(ctxt.Arch, got, int64(s.Got()))
-		rel.AddUint32(ctxt.Arch, ld.ELF32_R_INFO(uint32(s.Dynid), uint32(elf.R_ARM_GLOB_DAT)))
-	} else {
-		ld.Errorf(s, "addgotsym: unsupported binary format")
-	}
-}
-
-func asmb(ctxt *ld.Link) {
-	if ctxt.IsELF {
-		ld.Asmbelfsetup()
-	}
-
-	sect := ld.Segtext.Sections[0]
-	ctxt.Out.SeekSet(int64(sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff))
-	ld.Codeblk(ctxt, int64(sect.Vaddr), int64(sect.Length))
-	for _, sect = range ld.Segtext.Sections[1:] {
-		ctxt.Out.SeekSet(int64(sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff))
-		ld.Datblk(ctxt, int64(sect.Vaddr), int64(sect.Length))
-	}
-
-	if ld.Segrodata.Filelen > 0 {
-		ctxt.Out.SeekSet(int64(ld.Segrodata.Fileoff))
-		ld.Datblk(ctxt, int64(ld.Segrodata.Vaddr), int64(ld.Segrodata.Filelen))
-	}
-	if ld.Segrelrodata.Filelen > 0 {
-		ctxt.Out.SeekSet(int64(ld.Segrelrodata.Fileoff))
-		ld.Datblk(ctxt, int64(ld.Segrelrodata.Vaddr), int64(ld.Segrelrodata.Filelen))
-	}
-
-	ctxt.Out.SeekSet(int64(ld.Segdata.Fileoff))
-	ld.Datblk(ctxt, int64(ld.Segdata.Vaddr), int64(ld.Segdata.Filelen))
-
-	ctxt.Out.SeekSet(int64(ld.Segdwarf.Fileoff))
-	ld.Dwarfblk(ctxt, int64(ld.Segdwarf.Vaddr), int64(ld.Segdwarf.Filelen))
-}
-
-func asmb2(ctxt *ld.Link) {
-	/* output symbol table */
-	ld.Symsize = 0
-
-	ld.Lcsize = 0
-	symo := uint32(0)
-	if !*ld.FlagS {
-		// TODO: rationalize
-		switch ctxt.HeadType {
-		default:
-			if ctxt.IsELF {
-				symo = uint32(ld.Segdwarf.Fileoff + ld.Segdwarf.Filelen)
-				symo = uint32(ld.Rnd(int64(symo), int64(*ld.FlagRound)))
-			}
-
-		case objabi.Hplan9:
-			symo = uint32(ld.Segdata.Fileoff + ld.Segdata.Filelen)
-
-		case objabi.Hwindows:
-			symo = uint32(ld.Segdwarf.Fileoff + ld.Segdwarf.Filelen)
-			symo = uint32(ld.Rnd(int64(symo), ld.PEFILEALIGN))
-		}
-
-		ctxt.Out.SeekSet(int64(symo))
-		switch ctxt.HeadType {
-		default:
-			if ctxt.IsELF {
-				ld.Asmelfsym(ctxt)
-				ctxt.Out.Flush()
-				ctxt.Out.Write(ld.Elfstrdat)
-
-				if ctxt.LinkMode == ld.LinkExternal {
-					ld.Elfemitreloc(ctxt)
-				}
-			}
-
-		case objabi.Hplan9:
-			ld.Asmplan9sym(ctxt)
-			ctxt.Out.Flush()
-
-			sym := ctxt.Syms.Lookup("pclntab", 0)
-			if sym != nil {
-				ld.Lcsize = int32(len(sym.P))
-				ctxt.Out.Write(sym.P)
-				ctxt.Out.Flush()
-			}
-
-		case objabi.Hwindows:
-			// Do nothing
-		}
-	}
-
-	ctxt.Out.SeekSet(0)
-	switch ctxt.HeadType {
-	default:
-	case objabi.Hplan9: /* plan 9 */
-		ctxt.Out.Write32b(0x647)                      /* magic */
-		ctxt.Out.Write32b(uint32(ld.Segtext.Filelen)) /* sizes */
-		ctxt.Out.Write32b(uint32(ld.Segdata.Filelen))
-		ctxt.Out.Write32b(uint32(ld.Segdata.Length - ld.Segdata.Filelen))
-		ctxt.Out.Write32b(uint32(ld.Symsize))          /* nsyms */
-		ctxt.Out.Write32b(uint32(ld.Entryvalue(ctxt))) /* va of entry */
-		ctxt.Out.Write32b(0)
-		ctxt.Out.Write32b(uint32(ld.Lcsize))
-
-	case objabi.Hlinux,
-		objabi.Hfreebsd,
-		objabi.Hnetbsd,
-		objabi.Hopenbsd:
-		ld.Asmbelf(ctxt, int64(symo))
-
-	case objabi.Hwindows:
-		ld.Asmbpe(ctxt)
-	}
-
-	ctxt.Out.Flush()
-	if *ld.FlagC {
-		fmt.Printf("textsize=%d\n", ld.Segtext.Filelen)
-		fmt.Printf("datsize=%d\n", ld.Segdata.Filelen)
-		fmt.Printf("bsssize=%d\n", ld.Segdata.Length-ld.Segdata.Filelen)
-		fmt.Printf("symsize=%d\n", ld.Symsize)
-		fmt.Printf("lcsize=%d\n", ld.Lcsize)
-		fmt.Printf("total=%d\n", ld.Segtext.Filelen+ld.Segdata.Length+uint64(ld.Symsize)+uint64(ld.Lcsize))
-	}
-}
diff --git a/src/cmd/oldlink/internal/arm/l.go b/src/cmd/oldlink/internal/arm/l.go
deleted file mode 100644
index d16dc27..0000000
--- a/src/cmd/oldlink/internal/arm/l.go
+++ /dev/null
@@ -1,75 +0,0 @@
-// Inferno utils/5l/asm.c
-// https://bitbucket.org/inferno-os/inferno-os/src/master/utils/5l/asm.c
-//
-//	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 arm
-
-// Writing object files.
-
-// Inferno utils/5l/l.h
-// https://bitbucket.org/inferno-os/inferno-os/src/master/utils/5l/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.
-
-const (
-	maxAlign  = 8 // max data alignment
-	minAlign  = 1 // min data alignment
-	funcAlign = 4 // single-instruction alignment
-)
-
-/* Used by ../internal/ld/dwarf.go */
-const (
-	dwarfRegSP = 13
-	dwarfRegLR = 14
-)
diff --git a/src/cmd/oldlink/internal/arm/obj.go b/src/cmd/oldlink/internal/arm/obj.go
deleted file mode 100644
index 397990f..0000000
--- a/src/cmd/oldlink/internal/arm/obj.go
+++ /dev/null
@@ -1,107 +0,0 @@
-// Inferno utils/5l/obj.c
-// https://bitbucket.org/inferno-os/inferno-os/src/master/utils/5l/obj.c
-//
-//	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 arm
-
-import (
-	"cmd/internal/objabi"
-	"cmd/internal/sys"
-	"cmd/oldlink/internal/ld"
-)
-
-func Init() (*sys.Arch, ld.Arch) {
-	arch := sys.ArchARM
-
-	theArch := ld.Arch{
-		Funcalign:  funcAlign,
-		Maxalign:   maxAlign,
-		Minalign:   minAlign,
-		Dwarfregsp: dwarfRegSP,
-		Dwarfreglr: dwarfRegLR,
-
-		Adddynrel:        adddynrel,
-		Archinit:         archinit,
-		Archreloc:        archreloc,
-		Archrelocvariant: archrelocvariant,
-		Trampoline:       trampoline,
-		Asmb:             asmb,
-		Asmb2:            asmb2,
-		Elfreloc1:        elfreloc1,
-		Elfsetupplt:      elfsetupplt,
-		Gentext:          gentext,
-		Machoreloc1:      machoreloc1,
-		PEreloc1:         pereloc1,
-
-		Linuxdynld:     "/lib/ld-linux.so.3", // 2 for OABI, 3 for EABI
-		Freebsddynld:   "/usr/libexec/ld-elf.so.1",
-		Openbsddynld:   "/usr/libexec/ld.so",
-		Netbsddynld:    "/libexec/ld.elf_so",
-		Dragonflydynld: "XXX",
-		Solarisdynld:   "XXX",
-	}
-
-	return arch, theArch
-}
-
-func archinit(ctxt *ld.Link) {
-	switch ctxt.HeadType {
-	default:
-		ld.Exitf("unknown -H option: %v", ctxt.HeadType)
-
-	case objabi.Hplan9: /* plan 9 */
-		ld.HEADR = 32
-
-		if *ld.FlagTextAddr == -1 {
-			*ld.FlagTextAddr = 4128
-		}
-		if *ld.FlagRound == -1 {
-			*ld.FlagRound = 4096
-		}
-
-	case objabi.Hlinux, /* arm elf */
-		objabi.Hfreebsd,
-		objabi.Hnetbsd,
-		objabi.Hopenbsd:
-		*ld.FlagD = false
-		// with dynamic linking
-		ld.Elfinit(ctxt)
-		ld.HEADR = ld.ELFRESERVE
-		if *ld.FlagTextAddr == -1 {
-			*ld.FlagTextAddr = 0x10000 + int64(ld.HEADR)
-		}
-		if *ld.FlagRound == -1 {
-			*ld.FlagRound = 0x10000
-		}
-
-	case objabi.Hwindows: /* PE executable */
-		// ld.HEADR, ld.FlagTextAddr, ld.FlagRound are set in ld.Peinit
-		return
-	}
-}
diff --git a/src/cmd/oldlink/internal/arm64/asm.go b/src/cmd/oldlink/internal/arm64/asm.go
deleted file mode 100644
index 4f29fbe..0000000
--- a/src/cmd/oldlink/internal/arm64/asm.go
+++ /dev/null
@@ -1,946 +0,0 @@
-// Inferno utils/5l/asm.c
-// https://bitbucket.org/inferno-os/inferno-os/src/master/utils/5l/asm.c
-//
-//	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 arm64
-
-import (
-	"cmd/internal/objabi"
-	"cmd/internal/sys"
-	"cmd/oldlink/internal/ld"
-	"cmd/oldlink/internal/sym"
-	"debug/elf"
-	"encoding/binary"
-	"fmt"
-	"log"
-)
-
-func gentext(ctxt *ld.Link) {
-	if !ctxt.DynlinkingGo() {
-		return
-	}
-	addmoduledata := ctxt.Syms.Lookup("runtime.addmoduledata", 0)
-	if addmoduledata.Type == sym.STEXT && ctxt.BuildMode != ld.BuildModePlugin {
-		// we're linking a module containing the runtime -> no need for
-		// an init function
-		return
-	}
-	addmoduledata.Attr |= sym.AttrReachable
-	initfunc := ctxt.Syms.Lookup("go.link.addmoduledata", 0)
-	initfunc.Type = sym.STEXT
-	initfunc.Attr |= sym.AttrLocal
-	initfunc.Attr |= sym.AttrReachable
-	o := func(op uint32) {
-		initfunc.AddUint32(ctxt.Arch, op)
-	}
-	// 0000000000000000 <local.dso_init>:
-	// 0:	90000000 	adrp	x0, 0 <runtime.firstmoduledata>
-	// 	0: R_AARCH64_ADR_PREL_PG_HI21	local.moduledata
-	// 4:	91000000 	add	x0, x0, #0x0
-	// 	4: R_AARCH64_ADD_ABS_LO12_NC	local.moduledata
-	o(0x90000000)
-	o(0x91000000)
-	rel := initfunc.AddRel()
-	rel.Off = 0
-	rel.Siz = 8
-	rel.Sym = ctxt.Moduledata
-	rel.Type = objabi.R_ADDRARM64
-
-	// 8:	14000000 	b	0 <runtime.addmoduledata>
-	// 	8: R_AARCH64_CALL26	runtime.addmoduledata
-	o(0x14000000)
-	rel = initfunc.AddRel()
-	rel.Off = 8
-	rel.Siz = 4
-	rel.Sym = ctxt.Syms.Lookup("runtime.addmoduledata", 0)
-	rel.Type = objabi.R_CALLARM64 // Really should be R_AARCH64_JUMP26 but doesn't seem to make any difference
-
-	if ctxt.BuildMode == ld.BuildModePlugin {
-		ctxt.Textp = append(ctxt.Textp, addmoduledata)
-	}
-	ctxt.Textp = append(ctxt.Textp, initfunc)
-	initarray_entry := ctxt.Syms.Lookup("go.link.addmoduledatainit", 0)
-	initarray_entry.Attr |= sym.AttrReachable
-	initarray_entry.Attr |= sym.AttrLocal
-	initarray_entry.Type = sym.SINITARR
-	initarray_entry.AddAddr(ctxt.Arch, initfunc)
-}
-
-func adddynrel(ctxt *ld.Link, s *sym.Symbol, r *sym.Reloc) bool {
-	targ := r.Sym
-
-	switch r.Type {
-	default:
-		if r.Type >= objabi.ElfRelocOffset {
-			ld.Errorf(s, "unexpected relocation type %d (%s)", r.Type, sym.RelocName(ctxt.Arch, r.Type))
-			return false
-		}
-
-	// Handle relocations found in ELF object files.
-	case objabi.ElfRelocOffset + objabi.RelocType(elf.R_AARCH64_PREL32):
-		if targ.Type == sym.SDYNIMPORT {
-			ld.Errorf(s, "unexpected R_AARCH64_PREL32 relocation for dynamic symbol %s", targ.Name)
-		}
-		// TODO(mwhudson): the test of VisibilityHidden here probably doesn't make
-		// sense and should be removed when someone has thought about it properly.
-		if (targ.Type == 0 || targ.Type == sym.SXREF) && !targ.Attr.VisibilityHidden() {
-			ld.Errorf(s, "unknown symbol %s in pcrel", targ.Name)
-		}
-		r.Type = objabi.R_PCREL
-		r.Add += 4
-		return true
-
-	case objabi.ElfRelocOffset + objabi.RelocType(elf.R_AARCH64_PREL64):
-		if targ.Type == sym.SDYNIMPORT {
-			ld.Errorf(s, "unexpected R_AARCH64_PREL64 relocation for dynamic symbol %s", targ.Name)
-		}
-		if targ.Type == 0 || targ.Type == sym.SXREF {
-			ld.Errorf(s, "unknown symbol %s in pcrel", targ.Name)
-		}
-		r.Type = objabi.R_PCREL
-		r.Add += 8
-		return true
-
-	case objabi.ElfRelocOffset + objabi.RelocType(elf.R_AARCH64_CALL26),
-		objabi.ElfRelocOffset + objabi.RelocType(elf.R_AARCH64_JUMP26):
-		if targ.Type == sym.SDYNIMPORT {
-			addpltsym(ctxt, targ)
-			r.Sym = ctxt.Syms.Lookup(".plt", 0)
-			r.Add += int64(targ.Plt())
-		}
-		if (targ.Type == 0 || targ.Type == sym.SXREF) && !targ.Attr.VisibilityHidden() {
-			ld.Errorf(s, "unknown symbol %s in callarm64", targ.Name)
-		}
-		r.Type = objabi.R_CALLARM64
-		return true
-
-	case objabi.ElfRelocOffset + objabi.RelocType(elf.R_AARCH64_ADR_GOT_PAGE),
-		objabi.ElfRelocOffset + objabi.RelocType(elf.R_AARCH64_LD64_GOT_LO12_NC):
-		if targ.Type != sym.SDYNIMPORT {
-			// have symbol
-			// TODO: turn LDR of GOT entry into ADR of symbol itself
-		}
-
-		// fall back to using GOT
-		// TODO: just needs relocation, no need to put in .dynsym
-		addgotsym(ctxt, targ)
-
-		r.Type = objabi.R_ARM64_GOT
-		r.Sym = ctxt.Syms.Lookup(".got", 0)
-		r.Add += int64(targ.Got())
-		return true
-
-	case objabi.ElfRelocOffset + objabi.RelocType(elf.R_AARCH64_ADR_PREL_PG_HI21),
-		objabi.ElfRelocOffset + objabi.RelocType(elf.R_AARCH64_ADD_ABS_LO12_NC):
-		if targ.Type == sym.SDYNIMPORT {
-			ld.Errorf(s, "unexpected relocation for dynamic symbol %s", targ.Name)
-		}
-		if targ.Type == 0 || targ.Type == sym.SXREF {
-			ld.Errorf(s, "unknown symbol %s", targ.Name)
-		}
-		r.Type = objabi.R_ARM64_PCREL
-		return true
-
-	case objabi.ElfRelocOffset + objabi.RelocType(elf.R_AARCH64_ABS64):
-		if targ.Type == sym.SDYNIMPORT {
-			ld.Errorf(s, "unexpected R_AARCH64_ABS64 relocation for dynamic symbol %s", targ.Name)
-		}
-		r.Type = objabi.R_ADDR
-		if ctxt.BuildMode == ld.BuildModePIE && ctxt.LinkMode == ld.LinkInternal {
-			// For internal linking PIE, this R_ADDR relocation cannot
-			// be resolved statically. We need to generate a dynamic
-			// relocation. Let the code below handle it.
-			break
-		}
-		return true
-
-	case objabi.ElfRelocOffset + objabi.RelocType(elf.R_AARCH64_LDST8_ABS_LO12_NC):
-		if targ.Type == sym.SDYNIMPORT {
-			ld.Errorf(s, "unexpected relocation for dynamic symbol %s", targ.Name)
-		}
-		r.Type = objabi.R_ARM64_LDST8
-		return true
-
-	case objabi.ElfRelocOffset + objabi.RelocType(elf.R_AARCH64_LDST32_ABS_LO12_NC):
-		if targ.Type == sym.SDYNIMPORT {
-			ld.Errorf(s, "unexpected relocation for dynamic symbol %s", targ.Name)
-		}
-		r.Type = objabi.R_ARM64_LDST32
-		return true
-
-	case objabi.ElfRelocOffset + objabi.RelocType(elf.R_AARCH64_LDST64_ABS_LO12_NC):
-		if targ.Type == sym.SDYNIMPORT {
-			ld.Errorf(s, "unexpected relocation for dynamic symbol %s", targ.Name)
-		}
-		r.Type = objabi.R_ARM64_LDST64
-		return true
-
-	case objabi.ElfRelocOffset + objabi.RelocType(elf.R_AARCH64_LDST128_ABS_LO12_NC):
-		if targ.Type == sym.SDYNIMPORT {
-			ld.Errorf(s, "unexpected relocation for dynamic symbol %s", targ.Name)
-		}
-		r.Type = objabi.R_ARM64_LDST128
-		return true
-	}
-
-	switch r.Type {
-	case objabi.R_CALL,
-		objabi.R_PCREL,
-		objabi.R_CALLARM64:
-		if targ.Type != sym.SDYNIMPORT {
-			// nothing to do, the relocation will be laid out in reloc
-			return true
-		}
-		if ctxt.LinkMode == ld.LinkExternal {
-			// External linker will do this relocation.
-			return true
-		}
-
-	case objabi.R_ADDR:
-		if s.Type == sym.STEXT && ctxt.IsELF {
-			// The code is asking for the address of an external
-			// function. We provide it with the address of the
-			// correspondent GOT symbol.
-			addgotsym(ctxt, targ)
-
-			r.Sym = ctxt.Syms.Lookup(".got", 0)
-			r.Add += int64(targ.Got())
-			return true
-		}
-
-		// Process dynamic relocations for the data sections.
-		if ctxt.BuildMode == ld.BuildModePIE && ctxt.LinkMode == ld.LinkInternal {
-			// When internally linking, generate dynamic relocations
-			// for all typical R_ADDR relocations. The exception
-			// are those R_ADDR that are created as part of generating
-			// the dynamic relocations and must be resolved statically.
-			//
-			// There are three phases relevant to understanding this:
-			//
-			//	dodata()  // we are here
-			//	address() // symbol address assignment
-			//	reloc()   // resolution of static R_ADDR relocs
-			//
-			// At this point symbol addresses have not been
-			// assigned yet (as the final size of the .rela section
-			// will affect the addresses), and so we cannot write
-			// the Elf64_Rela.r_offset now. Instead we delay it
-			// until after the 'address' phase of the linker is
-			// complete. We do this via Addaddrplus, which creates
-			// a new R_ADDR relocation which will be resolved in
-			// the 'reloc' phase.
-			//
-			// These synthetic static R_ADDR relocs must be skipped
-			// now, or else we will be caught in an infinite loop
-			// of generating synthetic relocs for our synthetic
-			// relocs.
-			//
-			// Furthermore, the rela sections contain dynamic
-			// relocations with R_ADDR relocations on
-			// Elf64_Rela.r_offset. This field should contain the
-			// symbol offset as determined by reloc(), not the
-			// final dynamically linked address as a dynamic
-			// relocation would provide.
-			switch s.Name {
-			case ".dynsym", ".rela", ".rela.plt", ".got.plt", ".dynamic":
-				return false
-			}
-		} else {
-			// Either internally linking a static executable,
-			// in which case we can resolve these relocations
-			// statically in the 'reloc' phase, or externally
-			// linking, in which case the relocation will be
-			// prepared in the 'reloc' phase and passed to the
-			// external linker in the 'asmb' phase.
-			if s.Type != sym.SDATA && s.Type != sym.SRODATA {
-				break
-			}
-		}
-
-		if ctxt.IsELF {
-			// Generate R_AARCH64_RELATIVE relocations for best
-			// efficiency in the dynamic linker.
-			//
-			// As noted above, symbol addresses have not been
-			// assigned yet, so we can't generate the final reloc
-			// entry yet. We ultimately want:
-			//
-			// r_offset = s + r.Off
-			// r_info = R_AARCH64_RELATIVE
-			// r_addend = targ + r.Add
-			//
-			// The dynamic linker will set *offset = base address +
-			// addend.
-			//
-			// AddAddrPlus is used for r_offset and r_addend to
-			// generate new R_ADDR relocations that will update
-			// these fields in the 'reloc' phase.
-			rela := ctxt.Syms.Lookup(".rela", 0)
-			rela.AddAddrPlus(ctxt.Arch, s, int64(r.Off))
-			if r.Siz == 8 {
-				rela.AddUint64(ctxt.Arch, ld.ELF64_R_INFO(0, uint32(elf.R_AARCH64_RELATIVE)))
-			} else {
-				ld.Errorf(s, "unexpected relocation for dynamic symbol %s", targ.Name)
-			}
-			rela.AddAddrPlus(ctxt.Arch, targ, int64(r.Add))
-			// Not mark r done here. So we still apply it statically,
-			// so in the file content we'll also have the right offset
-			// to the relocation target. So it can be examined statically
-			// (e.g. go version).
-			return true
-		}
-	}
-	return false
-}
-
-func elfreloc1(ctxt *ld.Link, r *sym.Reloc, sectoff int64) bool {
-	ctxt.Out.Write64(uint64(sectoff))
-
-	elfsym := r.Xsym.ElfsymForReloc()
-	switch r.Type {
-	default:
-		return false
-	case objabi.R_ADDR:
-		switch r.Siz {
-		case 4:
-			ctxt.Out.Write64(uint64(elf.R_AARCH64_ABS32) | uint64(elfsym)<<32)
-		case 8:
-			ctxt.Out.Write64(uint64(elf.R_AARCH64_ABS64) | uint64(elfsym)<<32)
-		default:
-			return false
-		}
-	case objabi.R_ADDRARM64:
-		// two relocations: R_AARCH64_ADR_PREL_PG_HI21 and R_AARCH64_ADD_ABS_LO12_NC
-		ctxt.Out.Write64(uint64(elf.R_AARCH64_ADR_PREL_PG_HI21) | uint64(elfsym)<<32)
-		ctxt.Out.Write64(uint64(r.Xadd))
-		ctxt.Out.Write64(uint64(sectoff + 4))
-		ctxt.Out.Write64(uint64(elf.R_AARCH64_ADD_ABS_LO12_NC) | uint64(elfsym)<<32)
-	case objabi.R_ARM64_TLS_LE:
-		ctxt.Out.Write64(uint64(elf.R_AARCH64_TLSLE_MOVW_TPREL_G0) | uint64(elfsym)<<32)
-	case objabi.R_ARM64_TLS_IE:
-		ctxt.Out.Write64(uint64(elf.R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21) | uint64(elfsym)<<32)
-		ctxt.Out.Write64(uint64(r.Xadd))
-		ctxt.Out.Write64(uint64(sectoff + 4))
-		ctxt.Out.Write64(uint64(elf.R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC) | uint64(elfsym)<<32)
-	case objabi.R_ARM64_GOTPCREL:
-		ctxt.Out.Write64(uint64(elf.R_AARCH64_ADR_GOT_PAGE) | uint64(elfsym)<<32)
-		ctxt.Out.Write64(uint64(r.Xadd))
-		ctxt.Out.Write64(uint64(sectoff + 4))
-		ctxt.Out.Write64(uint64(elf.R_AARCH64_LD64_GOT_LO12_NC) | uint64(elfsym)<<32)
-	case objabi.R_CALLARM64:
-		if r.Siz != 4 {
-			return false
-		}
-		ctxt.Out.Write64(uint64(elf.R_AARCH64_CALL26) | uint64(elfsym)<<32)
-
-	}
-	ctxt.Out.Write64(uint64(r.Xadd))
-
-	return true
-}
-
-func machoreloc1(arch *sys.Arch, out *ld.OutBuf, s *sym.Symbol, r *sym.Reloc, sectoff int64) bool {
-	var v uint32
-
-	rs := r.Xsym
-
-	if rs.Type == sym.SHOSTOBJ || r.Type == objabi.R_CALLARM64 || r.Type == objabi.R_ADDRARM64 {
-		if rs.Dynid < 0 {
-			ld.Errorf(s, "reloc %d (%s) to non-macho symbol %s type=%d (%s)", r.Type, sym.RelocName(arch, r.Type), rs.Name, rs.Type, rs.Type)
-			return false
-		}
-
-		v = uint32(rs.Dynid)
-		v |= 1 << 27 // external relocation
-	} else {
-		v = uint32(rs.Sect.Extnum)
-		if v == 0 {
-			ld.Errorf(s, "reloc %d (%s) to symbol %s in non-macho section %s type=%d (%s)", r.Type, sym.RelocName(arch, r.Type), rs.Name, rs.Sect.Name, rs.Type, rs.Type)
-			return false
-		}
-	}
-
-	switch r.Type {
-	default:
-		return false
-	case objabi.R_ADDR:
-		v |= ld.MACHO_ARM64_RELOC_UNSIGNED << 28
-	case objabi.R_CALLARM64:
-		if r.Xadd != 0 {
-			ld.Errorf(s, "ld64 doesn't allow BR26 reloc with non-zero addend: %s+%d", rs.Name, r.Xadd)
-		}
-
-		v |= 1 << 24 // pc-relative bit
-		v |= ld.MACHO_ARM64_RELOC_BRANCH26 << 28
-	case objabi.R_ADDRARM64:
-		r.Siz = 4
-		// Two relocation entries: MACHO_ARM64_RELOC_PAGEOFF12 MACHO_ARM64_RELOC_PAGE21
-		// if r.Xadd is non-zero, add two MACHO_ARM64_RELOC_ADDEND.
-		if r.Xadd != 0 {
-			out.Write32(uint32(sectoff + 4))
-			out.Write32((ld.MACHO_ARM64_RELOC_ADDEND << 28) | (2 << 25) | uint32(r.Xadd&0xffffff))
-		}
-		out.Write32(uint32(sectoff + 4))
-		out.Write32(v | (ld.MACHO_ARM64_RELOC_PAGEOFF12 << 28) | (2 << 25))
-		if r.Xadd != 0 {
-			out.Write32(uint32(sectoff))
-			out.Write32((ld.MACHO_ARM64_RELOC_ADDEND << 28) | (2 << 25) | uint32(r.Xadd&0xffffff))
-		}
-		v |= 1 << 24 // pc-relative bit
-		v |= ld.MACHO_ARM64_RELOC_PAGE21 << 28
-	}
-
-	switch r.Siz {
-	default:
-		return false
-	case 1:
-		v |= 0 << 25
-	case 2:
-		v |= 1 << 25
-	case 4:
-		v |= 2 << 25
-	case 8:
-		v |= 3 << 25
-	}
-
-	out.Write32(uint32(sectoff))
-	out.Write32(v)
-	return true
-}
-
-func archreloc(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, val int64) (int64, bool) {
-	if ctxt.LinkMode == ld.LinkExternal {
-		switch r.Type {
-		default:
-			return val, false
-		case objabi.R_ARM64_GOTPCREL:
-			var o1, o2 uint32
-			if ctxt.Arch.ByteOrder == binary.BigEndian {
-				o1 = uint32(val >> 32)
-				o2 = uint32(val)
-			} else {
-				o1 = uint32(val)
-				o2 = uint32(val >> 32)
-			}
-			// Any relocation against a function symbol is redirected to
-			// be against a local symbol instead (see putelfsym in
-			// symtab.go) but unfortunately the system linker was buggy
-			// when confronted with a R_AARCH64_ADR_GOT_PAGE relocation
-			// against a local symbol until May 2015
-			// (https://sourceware.org/bugzilla/show_bug.cgi?id=18270). So
-			// we convert the adrp; ld64 + R_ARM64_GOTPCREL into adrp;
-			// add + R_ADDRARM64.
-			if !(r.Sym.IsFileLocal() || r.Sym.Attr.VisibilityHidden() || r.Sym.Attr.Local()) && r.Sym.Type == sym.STEXT && ctxt.DynlinkingGo() {
-				if o2&0xffc00000 != 0xf9400000 {
-					ld.Errorf(s, "R_ARM64_GOTPCREL against unexpected instruction %x", o2)
-				}
-				o2 = 0x91000000 | (o2 & 0x000003ff)
-				r.Type = objabi.R_ADDRARM64
-			}
-			if ctxt.Arch.ByteOrder == binary.BigEndian {
-				val = int64(o1)<<32 | int64(o2)
-			} else {
-				val = int64(o2)<<32 | int64(o1)
-			}
-			fallthrough
-		case objabi.R_ADDRARM64:
-			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 += ld.Symaddr(rs) - ld.Symaddr(rs.Outer)
-				rs = rs.Outer
-			}
-
-			if rs.Type != sym.SHOSTOBJ && rs.Type != sym.SDYNIMPORT && rs.Sect == nil {
-				ld.Errorf(s, "missing section for %s", rs.Name)
-			}
-			r.Xsym = rs
-
-			// Note: ld64 currently has a bug that any non-zero addend for BR26 relocation
-			// will make the linking fail because it thinks the code is not PIC even though
-			// the BR26 relocation should be fully resolved at link time.
-			// That is the reason why the next if block is disabled. When the bug in ld64
-			// is fixed, we can enable this block and also enable duff's device in cmd/7g.
-			if false && ctxt.HeadType == objabi.Hdarwin {
-				var o0, o1 uint32
-
-				if ctxt.Arch.ByteOrder == binary.BigEndian {
-					o0 = uint32(val >> 32)
-					o1 = uint32(val)
-				} else {
-					o0 = uint32(val)
-					o1 = uint32(val >> 32)
-				}
-				// Mach-O wants the addend to be encoded in the instruction
-				// Note that although Mach-O supports ARM64_RELOC_ADDEND, it
-				// can only encode 24-bit of signed addend, but the instructions
-				// supports 33-bit of signed addend, so we always encode the
-				// addend in place.
-				o0 |= (uint32((r.Xadd>>12)&3) << 29) | (uint32((r.Xadd>>12>>2)&0x7ffff) << 5)
-				o1 |= uint32(r.Xadd&0xfff) << 10
-				r.Xadd = 0
-
-				// when laid out, the instruction order must always be o1, o2.
-				if ctxt.Arch.ByteOrder == binary.BigEndian {
-					val = int64(o0)<<32 | int64(o1)
-				} else {
-					val = int64(o1)<<32 | int64(o0)
-				}
-			}
-
-			return val, true
-		case objabi.R_CALLARM64,
-			objabi.R_ARM64_TLS_LE,
-			objabi.R_ARM64_TLS_IE:
-			r.Done = false
-			r.Xsym = r.Sym
-			r.Xadd = r.Add
-			return val, true
-		}
-	}
-
-	switch r.Type {
-	case objabi.R_CONST:
-		return r.Add, true
-
-	case objabi.R_GOTOFF:
-		return ld.Symaddr(r.Sym) + r.Add - ld.Symaddr(ctxt.Syms.Lookup(".got", 0)), true
-
-	case objabi.R_ADDRARM64:
-		t := ld.Symaddr(r.Sym) + r.Add - ((s.Value + int64(r.Off)) &^ 0xfff)
-		if t >= 1<<32 || t < -1<<32 {
-			ld.Errorf(s, "program too large, address relocation distance = %d", t)
-		}
-
-		var o0, o1 uint32
-
-		if ctxt.Arch.ByteOrder == binary.BigEndian {
-			o0 = uint32(val >> 32)
-			o1 = uint32(val)
-		} else {
-			o0 = uint32(val)
-			o1 = uint32(val >> 32)
-		}
-
-		o0 |= (uint32((t>>12)&3) << 29) | (uint32((t>>12>>2)&0x7ffff) << 5)
-		o1 |= uint32(t&0xfff) << 10
-
-		// when laid out, the instruction order must always be o1, o2.
-		if ctxt.Arch.ByteOrder == binary.BigEndian {
-			return int64(o0)<<32 | int64(o1), true
-		}
-		return int64(o1)<<32 | int64(o0), true
-
-	case objabi.R_ARM64_TLS_LE:
-		r.Done = false
-		if ctxt.HeadType == objabi.Hdarwin {
-			ld.Errorf(s, "TLS reloc on unsupported OS %v", ctxt.HeadType)
-		}
-		// The TCB is two pointers. This is not documented anywhere, but is
-		// de facto part of the ABI.
-		v := r.Sym.Value + int64(2*ctxt.Arch.PtrSize)
-		if v < 0 || v >= 32678 {
-			ld.Errorf(s, "TLS offset out of range %d", v)
-		}
-		return val | (v << 5), true
-
-	case objabi.R_ARM64_TLS_IE:
-		if ctxt.BuildMode == ld.BuildModePIE && ctxt.IsELF {
-			// We are linking the final executable, so we
-			// can optimize any TLS IE relocation to LE.
-			r.Done = false
-			if ctxt.HeadType != objabi.Hlinux {
-				ld.Errorf(s, "TLS reloc on unsupported OS %v", ctxt.HeadType)
-			}
-
-			// The TCB is two pointers. This is not documented anywhere, but is
-			// de facto part of the ABI.
-			v := ld.Symaddr(r.Sym) + int64(2*ctxt.Arch.PtrSize) + r.Add
-			if v < 0 || v >= 32678 {
-				ld.Errorf(s, "TLS offset out of range %d", v)
-			}
-
-			var o0, o1 uint32
-			if ctxt.Arch.ByteOrder == binary.BigEndian {
-				o0 = uint32(val >> 32)
-				o1 = uint32(val)
-			} else {
-				o0 = uint32(val)
-				o1 = uint32(val >> 32)
-			}
-
-			// R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21
-			// turn ADRP to MOVZ
-			o0 = 0xd2a00000 | uint32(o0&0x1f) | (uint32((v>>16)&0xffff) << 5)
-			// R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC
-			// turn LD64 to MOVK
-			if v&3 != 0 {
-				ld.Errorf(s, "invalid address: %x for relocation type: R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC", v)
-			}
-			o1 = 0xf2800000 | uint32(o1&0x1f) | (uint32(v&0xffff) << 5)
-
-			// when laid out, the instruction order must always be o0, o1.
-			if ctxt.Arch.ByteOrder == binary.BigEndian {
-				return int64(o0)<<32 | int64(o1), true
-			}
-			return int64(o1)<<32 | int64(o0), true
-		} else {
-			log.Fatalf("cannot handle R_ARM64_TLS_IE (sym %s) when linking internally", s.Name)
-		}
-
-	case objabi.R_CALLARM64:
-		var t int64
-		if r.Sym.Type == sym.SDYNIMPORT {
-			t = (ld.Symaddr(ctxt.Syms.Lookup(".plt", 0)) + r.Add) - (s.Value + int64(r.Off))
-		} else {
-			t = (ld.Symaddr(r.Sym) + r.Add) - (s.Value + int64(r.Off))
-		}
-		if t >= 1<<27 || t < -1<<27 {
-			ld.Errorf(s, "program too large, call relocation distance = %d", t)
-		}
-		return val | ((t >> 2) & 0x03ffffff), true
-
-	case objabi.R_ARM64_GOT:
-		if s.P[r.Off+3]&0x9f == 0x90 {
-			// R_AARCH64_ADR_GOT_PAGE
-			// patch instruction: adrp
-			t := ld.Symaddr(r.Sym) + r.Add - ((s.Value + int64(r.Off)) &^ 0xfff)
-			if t >= 1<<32 || t < -1<<32 {
-				ld.Errorf(s, "program too large, address relocation distance = %d", t)
-			}
-			var o0 uint32
-			o0 |= (uint32((t>>12)&3) << 29) | (uint32((t>>12>>2)&0x7ffff) << 5)
-			return val | int64(o0), true
-		} else if s.P[r.Off+3] == 0xf9 {
-			// R_AARCH64_LD64_GOT_LO12_NC
-			// patch instruction: ldr
-			t := ld.Symaddr(r.Sym) + r.Add - ((s.Value + int64(r.Off)) &^ 0xfff)
-			if t&7 != 0 {
-				ld.Errorf(s, "invalid address: %x for relocation type: R_AARCH64_LD64_GOT_LO12_NC", t)
-			}
-			var o1 uint32
-			o1 |= uint32(t&0xfff) << (10 - 3)
-			return val | int64(uint64(o1)), true
-		} else {
-			ld.Errorf(s, "unsupported instruction for %v R_GOTARM64", s.P[r.Off:r.Off+4])
-		}
-
-	case objabi.R_ARM64_PCREL:
-		if s.P[r.Off+3]&0x9f == 0x90 {
-			// R_AARCH64_ADR_PREL_PG_HI21
-			// patch instruction: adrp
-			t := ld.Symaddr(r.Sym) + r.Add - ((s.Value + int64(r.Off)) &^ 0xfff)
-			if t >= 1<<32 || t < -1<<32 {
-				ld.Errorf(s, "program too large, address relocation distance = %d", t)
-			}
-			o0 := (uint32((t>>12)&3) << 29) | (uint32((t>>12>>2)&0x7ffff) << 5)
-			return val | int64(o0), true
-		} else if s.P[r.Off+3]&0x91 == 0x91 {
-			// R_AARCH64_ADD_ABS_LO12_NC
-			// patch instruction: add
-			t := ld.Symaddr(r.Sym) + r.Add - ((s.Value + int64(r.Off)) &^ 0xfff)
-			o1 := uint32(t&0xfff) << 10
-			return val | int64(o1), true
-		} else {
-			ld.Errorf(s, "unsupported instruction for %v R_PCRELARM64", s.P[r.Off:r.Off+4])
-		}
-
-	case objabi.R_ARM64_LDST8:
-		t := ld.Symaddr(r.Sym) + r.Add - ((s.Value + int64(r.Off)) &^ 0xfff)
-		o0 := uint32(t&0xfff) << 10
-		return val | int64(o0), true
-
-	case objabi.R_ARM64_LDST32:
-		t := ld.Symaddr(r.Sym) + r.Add - ((s.Value + int64(r.Off)) &^ 0xfff)
-		if t&3 != 0 {
-			ld.Errorf(s, "invalid address: %x for relocation type: R_AARCH64_LDST32_ABS_LO12_NC", t)
-		}
-		o0 := (uint32(t&0xfff) >> 2) << 10
-		return val | int64(o0), true
-
-	case objabi.R_ARM64_LDST64:
-		t := ld.Symaddr(r.Sym) + r.Add - ((s.Value + int64(r.Off)) &^ 0xfff)
-		if t&7 != 0 {
-			ld.Errorf(s, "invalid address: %x for relocation type: R_AARCH64_LDST64_ABS_LO12_NC", t)
-		}
-		o0 := (uint32(t&0xfff) >> 3) << 10
-		return val | int64(o0), true
-
-	case objabi.R_ARM64_LDST128:
-		t := ld.Symaddr(r.Sym) + r.Add - ((s.Value + int64(r.Off)) &^ 0xfff)
-		if t&15 != 0 {
-			ld.Errorf(s, "invalid address: %x for relocation type: R_AARCH64_LDST128_ABS_LO12_NC", t)
-		}
-		o0 := (uint32(t&0xfff) >> 4) << 10
-		return val | int64(o0), true
-	}
-
-	return val, false
-}
-
-func archrelocvariant(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, t int64) int64 {
-	log.Fatalf("unexpected relocation variant")
-	return -1
-}
-
-func elfsetupplt(ctxt *ld.Link) {
-	plt := ctxt.Syms.Lookup(".plt", 0)
-	gotplt := ctxt.Syms.Lookup(".got.plt", 0)
-	if plt.Size == 0 {
-		// stp     x16, x30, [sp, #-16]!
-		// identifying information
-		plt.AddUint32(ctxt.Arch, 0xa9bf7bf0)
-
-		// the following two instructions (adrp + ldr) load *got[2] into x17
-		// adrp    x16, &got[0]
-		plt.AddAddrPlus4(gotplt, 16)
-		plt.SetUint32(ctxt.Arch, plt.Size-4, 0x90000010)
-		plt.R[len(plt.R)-1].Type = objabi.R_ARM64_GOT
-
-		// <imm> is the offset value of &got[2] to &got[0], the same below
-		// ldr     x17, [x16, <imm>]
-		plt.AddAddrPlus4(gotplt, 16)
-		plt.SetUint32(ctxt.Arch, plt.Size-4, 0xf9400211)
-		plt.R[len(plt.R)-1].Type = objabi.R_ARM64_GOT
-
-		// add     x16, x16, <imm>
-		plt.AddAddrPlus4(gotplt, 16)
-		plt.SetUint32(ctxt.Arch, plt.Size-4, 0x91000210)
-		plt.R[len(plt.R)-1].Type = objabi.R_ARM64_PCREL
-
-		// br      x17
-		plt.AddUint32(ctxt.Arch, 0xd61f0220)
-
-		// 3 nop for place holder
-		plt.AddUint32(ctxt.Arch, 0xd503201f)
-		plt.AddUint32(ctxt.Arch, 0xd503201f)
-		plt.AddUint32(ctxt.Arch, 0xd503201f)
-
-		// check gotplt.size == 0
-		if gotplt.Size != 0 {
-			ld.Errorf(gotplt, "got.plt is not empty at the very beginning")
-		}
-		gotplt.AddAddrPlus(ctxt.Arch, ctxt.Syms.Lookup(".dynamic", 0), 0)
-
-		gotplt.AddUint64(ctxt.Arch, 0)
-		gotplt.AddUint64(ctxt.Arch, 0)
-	}
-}
-
-func addpltsym(ctxt *ld.Link, s *sym.Symbol) {
-	if s.Plt() >= 0 {
-		return
-	}
-
-	ld.Adddynsym(ctxt, s)
-
-	if ctxt.IsELF {
-		plt := ctxt.Syms.Lookup(".plt", 0)
-		gotplt := ctxt.Syms.Lookup(".got.plt", 0)
-		rela := ctxt.Syms.Lookup(".rela.plt", 0)
-		if plt.Size == 0 {
-			elfsetupplt(ctxt)
-		}
-
-		// adrp    x16, &got.plt[0]
-		plt.AddAddrPlus4(gotplt, gotplt.Size)
-		plt.SetUint32(ctxt.Arch, plt.Size-4, 0x90000010)
-		plt.R[len(plt.R)-1].Type = objabi.R_ARM64_GOT
-
-		// <offset> is the offset value of &got.plt[n] to &got.plt[0]
-		// ldr     x17, [x16, <offset>]
-		plt.AddAddrPlus4(gotplt, gotplt.Size)
-		plt.SetUint32(ctxt.Arch, plt.Size-4, 0xf9400211)
-		plt.R[len(plt.R)-1].Type = objabi.R_ARM64_GOT
-
-		// add     x16, x16, <offset>
-		plt.AddAddrPlus4(gotplt, gotplt.Size)
-		plt.SetUint32(ctxt.Arch, plt.Size-4, 0x91000210)
-		plt.R[len(plt.R)-1].Type = objabi.R_ARM64_PCREL
-
-		// br      x17
-		plt.AddUint32(ctxt.Arch, 0xd61f0220)
-
-		// add to got.plt: pointer to plt[0]
-		gotplt.AddAddrPlus(ctxt.Arch, plt, 0)
-
-		// rela
-		rela.AddAddrPlus(ctxt.Arch, gotplt, gotplt.Size-8)
-		rela.AddUint64(ctxt.Arch, ld.ELF64_R_INFO(uint32(s.Dynid), uint32(elf.R_AARCH64_JUMP_SLOT)))
-		rela.AddUint64(ctxt.Arch, 0)
-
-		s.SetPlt(int32(plt.Size - 16))
-	} else {
-		ld.Errorf(s, "addpltsym: unsupported binary format")
-	}
-}
-
-func addgotsym(ctxt *ld.Link, s *sym.Symbol) {
-	if s.Got() >= 0 {
-		return
-	}
-
-	ld.Adddynsym(ctxt, s)
-	got := ctxt.Syms.Lookup(".got", 0)
-	s.SetGot(int32(got.Size))
-	got.AddUint64(ctxt.Arch, 0)
-
-	if ctxt.IsELF {
-		rela := ctxt.Syms.Lookup(".rela", 0)
-		rela.AddAddrPlus(ctxt.Arch, got, int64(s.Got()))
-		rela.AddUint64(ctxt.Arch, ld.ELF64_R_INFO(uint32(s.Dynid), uint32(elf.R_AARCH64_GLOB_DAT)))
-		rela.AddUint64(ctxt.Arch, 0)
-	} else {
-		ld.Errorf(s, "addgotsym: unsupported binary format")
-	}
-}
-
-func asmb(ctxt *ld.Link) {
-	if ctxt.IsELF {
-		ld.Asmbelfsetup()
-	}
-
-	sect := ld.Segtext.Sections[0]
-	ctxt.Out.SeekSet(int64(sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff))
-	ld.Codeblk(ctxt, int64(sect.Vaddr), int64(sect.Length))
-	for _, sect = range ld.Segtext.Sections[1:] {
-		ctxt.Out.SeekSet(int64(sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff))
-		ld.Datblk(ctxt, int64(sect.Vaddr), int64(sect.Length))
-	}
-
-	if ld.Segrodata.Filelen > 0 {
-		ctxt.Out.SeekSet(int64(ld.Segrodata.Fileoff))
-		ld.Datblk(ctxt, int64(ld.Segrodata.Vaddr), int64(ld.Segrodata.Filelen))
-	}
-	if ld.Segrelrodata.Filelen > 0 {
-		ctxt.Out.SeekSet(int64(ld.Segrelrodata.Fileoff))
-		ld.Datblk(ctxt, int64(ld.Segrelrodata.Vaddr), int64(ld.Segrelrodata.Filelen))
-	}
-
-	ctxt.Out.SeekSet(int64(ld.Segdata.Fileoff))
-	ld.Datblk(ctxt, int64(ld.Segdata.Vaddr), int64(ld.Segdata.Filelen))
-
-	ctxt.Out.SeekSet(int64(ld.Segdwarf.Fileoff))
-	ld.Dwarfblk(ctxt, int64(ld.Segdwarf.Vaddr), int64(ld.Segdwarf.Filelen))
-}
-
-func asmb2(ctxt *ld.Link) {
-	machlink := uint32(0)
-	if ctxt.HeadType == objabi.Hdarwin {
-		machlink = uint32(ld.Domacholink(ctxt))
-	}
-
-	/* output symbol table */
-	ld.Symsize = 0
-
-	ld.Lcsize = 0
-	symo := uint32(0)
-	if !*ld.FlagS {
-		// TODO: rationalize
-		switch ctxt.HeadType {
-		default:
-			if ctxt.IsELF {
-				symo = uint32(ld.Segdwarf.Fileoff + ld.Segdwarf.Filelen)
-				symo = uint32(ld.Rnd(int64(symo), int64(*ld.FlagRound)))
-			}
-
-		case objabi.Hplan9:
-			symo = uint32(ld.Segdata.Fileoff + ld.Segdata.Filelen)
-
-		case objabi.Hdarwin:
-			symo = uint32(ld.Segdwarf.Fileoff + uint64(ld.Rnd(int64(ld.Segdwarf.Filelen), int64(*ld.FlagRound))) + uint64(machlink))
-		}
-
-		ctxt.Out.SeekSet(int64(symo))
-		switch ctxt.HeadType {
-		default:
-			if ctxt.IsELF {
-				ld.Asmelfsym(ctxt)
-				ctxt.Out.Flush()
-				ctxt.Out.Write(ld.Elfstrdat)
-
-				if ctxt.LinkMode == ld.LinkExternal {
-					ld.Elfemitreloc(ctxt)
-				}
-			}
-
-		case objabi.Hplan9:
-			ld.Asmplan9sym(ctxt)
-			ctxt.Out.Flush()
-
-			sym := ctxt.Syms.Lookup("pclntab", 0)
-			if sym != nil {
-				ld.Lcsize = int32(len(sym.P))
-				ctxt.Out.Write(sym.P)
-				ctxt.Out.Flush()
-			}
-
-		case objabi.Hdarwin:
-			if ctxt.LinkMode == ld.LinkExternal {
-				ld.Machoemitreloc(ctxt)
-			}
-		}
-	}
-
-	ctxt.Out.SeekSet(0)
-	switch ctxt.HeadType {
-	default:
-	case objabi.Hplan9: /* plan 9 */
-		ctxt.Out.Write32(0x647)                      /* magic */
-		ctxt.Out.Write32(uint32(ld.Segtext.Filelen)) /* sizes */
-		ctxt.Out.Write32(uint32(ld.Segdata.Filelen))
-		ctxt.Out.Write32(uint32(ld.Segdata.Length - ld.Segdata.Filelen))
-		ctxt.Out.Write32(uint32(ld.Symsize))          /* nsyms */
-		ctxt.Out.Write32(uint32(ld.Entryvalue(ctxt))) /* va of entry */
-		ctxt.Out.Write32(0)
-		ctxt.Out.Write32(uint32(ld.Lcsize))
-
-	case objabi.Hlinux,
-		objabi.Hfreebsd,
-		objabi.Hnetbsd,
-		objabi.Hopenbsd:
-		ld.Asmbelf(ctxt, int64(symo))
-
-	case objabi.Hdarwin:
-		ld.Asmbmacho(ctxt)
-	}
-
-	ctxt.Out.Flush()
-	if *ld.FlagC {
-		fmt.Printf("textsize=%d\n", ld.Segtext.Filelen)
-		fmt.Printf("datsize=%d\n", ld.Segdata.Filelen)
-		fmt.Printf("bsssize=%d\n", ld.Segdata.Length-ld.Segdata.Filelen)
-		fmt.Printf("symsize=%d\n", ld.Symsize)
-		fmt.Printf("lcsize=%d\n", ld.Lcsize)
-		fmt.Printf("total=%d\n", ld.Segtext.Filelen+ld.Segdata.Length+uint64(ld.Symsize)+uint64(ld.Lcsize))
-	}
-}
diff --git a/src/cmd/oldlink/internal/arm64/l.go b/src/cmd/oldlink/internal/arm64/l.go
deleted file mode 100644
index 4aa2708..0000000
--- a/src/cmd/oldlink/internal/arm64/l.go
+++ /dev/null
@@ -1,74 +0,0 @@
-// Inferno utils/5l/asm.c
-// https://bitbucket.org/inferno-os/inferno-os/src/master/utils/5l/asm.c
-//
-//	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 arm64
-
-// Writing object files.
-
-// cmd/9l/l.h from Vita Nuova.
-//
-//	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-2008 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-2008 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.
-
-const (
-	maxAlign  = 32 // max data alignment
-	minAlign  = 1  // min data alignment
-	funcAlign = 16
-)
-
-/* Used by ../internal/ld/dwarf.go */
-const (
-	dwarfRegSP = 31
-	dwarfRegLR = 30
-)
diff --git a/src/cmd/oldlink/internal/arm64/obj.go b/src/cmd/oldlink/internal/arm64/obj.go
deleted file mode 100644
index b5be5ec..0000000
--- a/src/cmd/oldlink/internal/arm64/obj.go
+++ /dev/null
@@ -1,110 +0,0 @@
-// Inferno utils/5l/obj.c
-// https://bitbucket.org/inferno-os/inferno-os/src/master/utils/5l/obj.c
-//
-//	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 arm64
-
-import (
-	"cmd/internal/objabi"
-	"cmd/internal/sys"
-	"cmd/oldlink/internal/ld"
-)
-
-func Init() (*sys.Arch, ld.Arch) {
-	arch := sys.ArchARM64
-
-	theArch := ld.Arch{
-		Funcalign:  funcAlign,
-		Maxalign:   maxAlign,
-		Minalign:   minAlign,
-		Dwarfregsp: dwarfRegSP,
-		Dwarfreglr: dwarfRegLR,
-
-		Adddynrel:        adddynrel,
-		Archinit:         archinit,
-		Archreloc:        archreloc,
-		Archrelocvariant: archrelocvariant,
-		Asmb:             asmb,
-		Asmb2:            asmb2,
-		Elfreloc1:        elfreloc1,
-		Elfsetupplt:      elfsetupplt,
-		Gentext:          gentext,
-		Machoreloc1:      machoreloc1,
-
-		Androiddynld: "/system/bin/linker64",
-		Linuxdynld:   "/lib/ld-linux-aarch64.so.1",
-
-		Freebsddynld:   "/usr/libexec/ld-elf.so.1",
-		Openbsddynld:   "/usr/libexec/ld.so",
-		Netbsddynld:    "/libexec/ld.elf_so",
-		Dragonflydynld: "XXX",
-		Solarisdynld:   "XXX",
-	}
-
-	return arch, theArch
-}
-
-func archinit(ctxt *ld.Link) {
-	switch ctxt.HeadType {
-	default:
-		ld.Exitf("unknown -H option: %v", ctxt.HeadType)
-
-	case objabi.Hplan9: /* plan 9 */
-		ld.HEADR = 32
-
-		if *ld.FlagTextAddr == -1 {
-			*ld.FlagTextAddr = 4096 + int64(ld.HEADR)
-		}
-		if *ld.FlagRound == -1 {
-			*ld.FlagRound = 4096
-		}
-
-	case objabi.Hlinux, /* arm64 elf */
-		objabi.Hfreebsd,
-		objabi.Hnetbsd,
-		objabi.Hopenbsd:
-		ld.Elfinit(ctxt)
-		ld.HEADR = ld.ELFRESERVE
-		if *ld.FlagTextAddr == -1 {
-			*ld.FlagTextAddr = 0x10000 + int64(ld.HEADR)
-		}
-		if *ld.FlagRound == -1 {
-			*ld.FlagRound = 0x10000
-		}
-
-	case objabi.Hdarwin: /* apple MACH */
-		ld.HEADR = ld.INITIAL_MACHO_HEADR
-		if *ld.FlagTextAddr == -1 {
-			*ld.FlagTextAddr = 4096 + int64(ld.HEADR)
-		}
-		if *ld.FlagRound == -1 {
-			*ld.FlagRound = 4096
-		}
-	}
-}
diff --git a/src/cmd/oldlink/internal/ld/ar.go b/src/cmd/oldlink/internal/ld/ar.go
deleted file mode 100644
index 453e12b..0000000
--- a/src/cmd/oldlink/internal/ld/ar.go
+++ /dev/null
@@ -1,193 +0,0 @@
-// Inferno utils/include/ar.h
-// https://bitbucket.org/inferno-os/inferno-os/src/master/utils/include/ar.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
-
-import (
-	"cmd/internal/bio"
-	"cmd/internal/objabi"
-	"cmd/oldlink/internal/sym"
-	"encoding/binary"
-	"fmt"
-	"io"
-	"os"
-)
-
-const (
-	SARMAG  = 8
-	SAR_HDR = 16 + 44
-)
-
-const (
-	ARMAG = "!<arch>\n"
-)
-
-type ArHdr struct {
-	name string
-	date string
-	uid  string
-	gid  string
-	mode string
-	size string
-	fmag string
-}
-
-// hostArchive reads an archive file holding host objects and links in
-// required objects. The general format is the same as a Go archive
-// file, but it has an armap listing symbols and the objects that
-// define them. This is used for the compiler support library
-// libgcc.a.
-func hostArchive(ctxt *Link, name string) {
-	f, err := bio.Open(name)
-	if err != nil {
-		if os.IsNotExist(err) {
-			// It's OK if we don't have a libgcc file at all.
-			if ctxt.Debugvlog != 0 {
-				ctxt.Logf("skipping libgcc file: %v\n", err)
-			}
-			return
-		}
-		Exitf("cannot open file %s: %v", name, err)
-	}
-	defer f.Close()
-
-	var magbuf [len(ARMAG)]byte
-	if _, err := io.ReadFull(f, magbuf[:]); err != nil {
-		Exitf("file %s too short", name)
-	}
-
-	if string(magbuf[:]) != ARMAG {
-		Exitf("%s is not an archive file", name)
-	}
-
-	var arhdr ArHdr
-	l := nextar(f, f.Offset(), &arhdr)
-	if l <= 0 {
-		Exitf("%s missing armap", name)
-	}
-
-	var armap archiveMap
-	if arhdr.name == "/" || arhdr.name == "/SYM64/" {
-		armap = readArmap(name, f, arhdr)
-	} else {
-		Exitf("%s missing armap", name)
-	}
-
-	loaded := make(map[uint64]bool)
-	any := true
-	for any {
-		var load []uint64
-		for _, s := range ctxt.Syms.Allsym {
-			for i := range s.R {
-				r := &s.R[i] // Copying sym.Reloc has measurable impact on performance
-				if r.Sym != nil && r.Sym.Type == sym.SXREF {
-					if off := armap[r.Sym.Name]; off != 0 && !loaded[off] {
-						load = append(load, off)
-						loaded[off] = true
-					}
-				}
-			}
-		}
-
-		for _, off := range load {
-			l := nextar(f, int64(off), &arhdr)
-			if l <= 0 {
-				Exitf("%s missing archive entry at offset %d", name, off)
-			}
-			pname := fmt.Sprintf("%s(%s)", name, arhdr.name)
-			l = atolwhex(arhdr.size)
-
-			libgcc := sym.Library{Pkg: "libgcc"}
-			h := ldobj(ctxt, f, &libgcc, l, pname, name)
-			f.MustSeek(h.off, 0)
-			h.ld(ctxt, f, h.pkg, h.length, h.pn)
-		}
-
-		any = len(load) > 0
-	}
-}
-
-// archiveMap is an archive symbol map: a mapping from symbol name to
-// offset within the archive file.
-type archiveMap map[string]uint64
-
-// readArmap reads the archive symbol map.
-func readArmap(filename string, f *bio.Reader, arhdr ArHdr) archiveMap {
-	is64 := arhdr.name == "/SYM64/"
-	wordSize := 4
-	if is64 {
-		wordSize = 8
-	}
-
-	contents := make([]byte, atolwhex(arhdr.size))
-	if _, err := io.ReadFull(f, contents); err != nil {
-		Exitf("short read from %s", filename)
-	}
-
-	var c uint64
-	if is64 {
-		c = binary.BigEndian.Uint64(contents)
-	} else {
-		c = uint64(binary.BigEndian.Uint32(contents))
-	}
-	contents = contents[wordSize:]
-
-	ret := make(archiveMap)
-
-	names := contents[c*uint64(wordSize):]
-	for i := uint64(0); i < c; i++ {
-		n := 0
-		for names[n] != 0 {
-			n++
-		}
-		name := string(names[:n])
-		names = names[n+1:]
-
-		// For Mach-O and PE/386 files we strip a leading
-		// underscore from the symbol name.
-		if objabi.GOOS == "darwin" || (objabi.GOOS == "windows" && objabi.GOARCH == "386") {
-			if name[0] == '_' && len(name) > 1 {
-				name = name[1:]
-			}
-		}
-
-		var off uint64
-		if is64 {
-			off = binary.BigEndian.Uint64(contents)
-		} else {
-			off = uint64(binary.BigEndian.Uint32(contents))
-		}
-		contents = contents[wordSize:]
-
-		ret[name] = off
-	}
-
-	return ret
-}
diff --git a/src/cmd/oldlink/internal/ld/config.go b/src/cmd/oldlink/internal/ld/config.go
deleted file mode 100644
index 2373b50..0000000
--- a/src/cmd/oldlink/internal/ld/config.go
+++ /dev/null
@@ -1,272 +0,0 @@
-// Copyright 2016 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/objabi"
-	"cmd/internal/sys"
-	"fmt"
-	"log"
-)
-
-// A BuildMode indicates the sort of object we are building.
-//
-// Possible build modes are the same as those for the -buildmode flag
-// in cmd/go, and are documented in 'go help buildmode'.
-type BuildMode uint8
-
-const (
-	BuildModeUnset BuildMode = iota
-	BuildModeExe
-	BuildModePIE
-	BuildModeCArchive
-	BuildModeCShared
-	BuildModeShared
-	BuildModePlugin
-)
-
-func (mode *BuildMode) Set(s string) error {
-	badmode := func() error {
-		return fmt.Errorf("buildmode %s not supported on %s/%s", s, objabi.GOOS, objabi.GOARCH)
-	}
-	switch s {
-	default:
-		return fmt.Errorf("invalid buildmode: %q", s)
-	case "exe":
-		*mode = BuildModeExe
-	case "pie":
-		switch objabi.GOOS {
-		case "aix", "android", "linux", "windows":
-		case "darwin", "freebsd":
-			switch objabi.GOARCH {
-			case "amd64":
-			default:
-				return badmode()
-			}
-		default:
-			return badmode()
-		}
-		*mode = BuildModePIE
-	case "c-archive":
-		switch objabi.GOOS {
-		case "aix", "darwin", "linux":
-		case "freebsd":
-			switch objabi.GOARCH {
-			case "amd64":
-			default:
-				return badmode()
-			}
-		case "windows":
-			switch objabi.GOARCH {
-			case "amd64", "386", "arm":
-			default:
-				return badmode()
-			}
-		default:
-			return badmode()
-		}
-		*mode = BuildModeCArchive
-	case "c-shared":
-		switch objabi.GOARCH {
-		case "386", "amd64", "arm", "arm64", "ppc64le", "s390x":
-		default:
-			return badmode()
-		}
-		*mode = BuildModeCShared
-	case "shared":
-		switch objabi.GOOS {
-		case "linux":
-			switch objabi.GOARCH {
-			case "386", "amd64", "arm", "arm64", "ppc64le", "s390x":
-			default:
-				return badmode()
-			}
-		default:
-			return badmode()
-		}
-		*mode = BuildModeShared
-	case "plugin":
-		switch objabi.GOOS {
-		case "linux":
-			switch objabi.GOARCH {
-			case "386", "amd64", "arm", "arm64", "s390x", "ppc64le":
-			default:
-				return badmode()
-			}
-		case "darwin", "freebsd":
-			switch objabi.GOARCH {
-			case "amd64":
-			default:
-				return badmode()
-			}
-		default:
-			return badmode()
-		}
-		*mode = BuildModePlugin
-	}
-	return nil
-}
-
-func (mode *BuildMode) String() string {
-	switch *mode {
-	case BuildModeUnset:
-		return "" // avoid showing a default in usage message
-	case BuildModeExe:
-		return "exe"
-	case BuildModePIE:
-		return "pie"
-	case BuildModeCArchive:
-		return "c-archive"
-	case BuildModeCShared:
-		return "c-shared"
-	case BuildModeShared:
-		return "shared"
-	case BuildModePlugin:
-		return "plugin"
-	}
-	return fmt.Sprintf("BuildMode(%d)", uint8(*mode))
-}
-
-// LinkMode indicates whether an external linker is used for the final link.
-type LinkMode uint8
-
-const (
-	LinkAuto LinkMode = iota
-	LinkInternal
-	LinkExternal
-)
-
-func (mode *LinkMode) Set(s string) error {
-	switch s {
-	default:
-		return fmt.Errorf("invalid linkmode: %q", s)
-	case "auto":
-		*mode = LinkAuto
-	case "internal":
-		*mode = LinkInternal
-	case "external":
-		*mode = LinkExternal
-	}
-	return nil
-}
-
-func (mode *LinkMode) String() string {
-	switch *mode {
-	case LinkAuto:
-		return "auto"
-	case LinkInternal:
-		return "internal"
-	case LinkExternal:
-		return "external"
-	}
-	return fmt.Sprintf("LinkMode(%d)", uint8(*mode))
-}
-
-// mustLinkExternal reports whether the program being linked requires
-// the external linker be used to complete the link.
-func mustLinkExternal(ctxt *Link) (res bool, reason string) {
-	if ctxt.Debugvlog > 1 {
-		defer func() {
-			if res {
-				log.Printf("external linking is forced by: %s\n", reason)
-			}
-		}()
-	}
-
-	if sys.MustLinkExternal(objabi.GOOS, objabi.GOARCH) {
-		return true, fmt.Sprintf("%s/%s requires external linking", objabi.GOOS, objabi.GOARCH)
-	}
-
-	if *flagMsan {
-		return true, "msan"
-	}
-
-	// Internally linking cgo is incomplete on some architectures.
-	// https://golang.org/issue/14449
-	// https://golang.org/issue/21961
-	if iscgo && ctxt.Arch.InFamily(sys.MIPS64, sys.MIPS, sys.PPC64) {
-		return true, objabi.GOARCH + " does not support internal cgo"
-	}
-	if iscgo && objabi.GOOS == "android" {
-		return true, objabi.GOOS + " does not support internal cgo"
-	}
-
-	// When the race flag is set, the LLVM tsan relocatable file is linked
-	// into the final binary, which means external linking is required because
-	// internal linking does not support it.
-	if *flagRace && ctxt.Arch.InFamily(sys.PPC64) {
-		return true, "race on " + objabi.GOARCH
-	}
-
-	// Some build modes require work the internal linker cannot do (yet).
-	switch ctxt.BuildMode {
-	case BuildModeCArchive:
-		return true, "buildmode=c-archive"
-	case BuildModeCShared:
-		return true, "buildmode=c-shared"
-	case BuildModePIE:
-		switch objabi.GOOS + "/" + objabi.GOARCH {
-		case "linux/amd64", "linux/arm64", "android/arm64":
-		case "windows/386", "windows/amd64", "windows/arm":
-		default:
-			// Internal linking does not support TLS_IE.
-			return true, "buildmode=pie"
-		}
-	case BuildModePlugin:
-		return true, "buildmode=plugin"
-	case BuildModeShared:
-		return true, "buildmode=shared"
-	}
-	if ctxt.linkShared {
-		return true, "dynamically linking with a shared library"
-	}
-
-	return false, ""
-}
-
-// determineLinkMode sets ctxt.LinkMode.
-//
-// It is called after flags are processed and inputs are processed,
-// so the ctxt.LinkMode variable has an initial value from the -linkmode
-// flag and the iscgo externalobj variables are set.
-func determineLinkMode(ctxt *Link) {
-	extNeeded, extReason := mustLinkExternal(ctxt)
-	via := ""
-
-	if ctxt.LinkMode == LinkAuto {
-		// The environment variable GO_EXTLINK_ENABLED controls the
-		// default value of -linkmode. If it is not set when the
-		// linker is called we take the value it was set to when
-		// cmd/link was compiled. (See make.bash.)
-		switch objabi.Getgoextlinkenabled() {
-		case "0":
-			ctxt.LinkMode = LinkInternal
-			via = "via GO_EXTLINK_ENABLED "
-		case "1":
-			ctxt.LinkMode = LinkExternal
-			via = "via GO_EXTLINK_ENABLED "
-		default:
-			if extNeeded || (iscgo && externalobj) {
-				ctxt.LinkMode = LinkExternal
-			} else {
-				ctxt.LinkMode = LinkInternal
-			}
-		}
-	}
-
-	switch ctxt.LinkMode {
-	case LinkInternal:
-		if extNeeded {
-			Exitf("internal linking requested %sbut external linking required: %s", via, extReason)
-		}
-	case LinkExternal:
-		switch {
-		case objabi.GOARCH == "riscv64":
-			Exitf("external linking not supported for %s/riscv64", objabi.GOOS)
-		case objabi.GOARCH == "ppc64" && objabi.GOOS != "aix":
-			Exitf("external linking not supported for %s/ppc64", objabi.GOOS)
-		}
-	}
-}
diff --git a/src/cmd/oldlink/internal/ld/data.go b/src/cmd/oldlink/internal/ld/data.go
deleted file mode 100644
index 02230cb..0000000
--- a/src/cmd/oldlink/internal/ld/data.go
+++ /dev/null
@@ -1,2501 +0,0 @@
-// Derived from Inferno utils/6l/obj.c and utils/6l/span.c
-// https://bitbucket.org/inferno-os/inferno-os/src/master/utils/6l/obj.c
-// https://bitbucket.org/inferno-os/inferno-os/src/master/utils/6l/span.c
-//
-//	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
-
-import (
-	"bufio"
-	"bytes"
-	"cmd/internal/gcprog"
-	"cmd/internal/objabi"
-	"cmd/internal/sys"
-	"cmd/oldlink/internal/sym"
-	"compress/zlib"
-	"encoding/binary"
-	"fmt"
-	"log"
-	"os"
-	"sort"
-	"strconv"
-	"strings"
-	"sync"
-)
-
-// isRuntimeDepPkg reports whether pkg is the runtime package or its dependency
-func isRuntimeDepPkg(pkg string) bool {
-	switch pkg {
-	case "runtime",
-		"sync/atomic",      // runtime may call to sync/atomic, due to go:linkname
-		"internal/bytealg", // for IndexByte
-		"internal/cpu":     // for cpu features
-		return true
-	}
-	return strings.HasPrefix(pkg, "runtime/internal/") && !strings.HasSuffix(pkg, "_test")
-}
-
-// Estimate the max size needed to hold any new trampolines created for this function. This
-// is used to determine when the section can be split if it becomes too large, to ensure that
-// the trampolines are in the same section as the function that uses them.
-func maxSizeTrampolinesPPC64(s *sym.Symbol, isTramp bool) uint64 {
-	// If thearch.Trampoline is nil, then trampoline support is not available on this arch.
-	// A trampoline does not need any dependent trampolines.
-	if thearch.Trampoline == nil || isTramp {
-		return 0
-	}
-
-	n := uint64(0)
-	for ri := range s.R {
-		r := &s.R[ri]
-		if r.Type.IsDirectCallOrJump() {
-			n++
-		}
-	}
-	// Trampolines in ppc64 are 4 instructions.
-	return n * 16
-}
-
-// detect too-far jumps in function s, and add trampolines if necessary
-// ARM, PPC64 & PPC64LE support trampoline insertion for internal and external linking
-// On PPC64 & PPC64LE the text sections might be split but will still insert trampolines
-// where necessary.
-func trampoline(ctxt *Link, s *sym.Symbol) {
-	if thearch.Trampoline == nil {
-		return // no need or no support of trampolines on this arch
-	}
-
-	for ri := range s.R {
-		r := &s.R[ri]
-		if !r.Type.IsDirectCallOrJump() {
-			continue
-		}
-		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)
-				}
-				// runtime and its dependent packages may call to each other.
-				// they are fine, as they will be laid down together.
-			}
-			continue
-		}
-
-		thearch.Trampoline(ctxt, r, s)
-	}
-
-}
-
-// 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
-//
-//  "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.
-func relocsym(ctxt *Link, s *sym.Symbol) {
-	if len(s.R) == 0 {
-		return
-	}
-	if s.Attr.ReadOnly() {
-		// The symbol's content is backed by read-only memory.
-		// Copy it to writable memory to apply relocations.
-		s.P = append([]byte(nil), s.P...)
-		s.Attr.Set(sym.AttrReadOnly, false)
-	}
-	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 ctxt.BuildMode == BuildModeShared || ctxt.BuildMode == BuildModePlugin {
-				if r.Sym.Name == "main.main" || (ctxt.BuildMode != BuildModePlugin && 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 {
-				ctxt.ErrorUnresolved(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 ctxt.HeadType != objabi.Hsolaris && ctxt.HeadType != objabi.Hdarwin && ctxt.HeadType != objabi.Haix && r.Sym != nil && r.Sym.Type == sym.SDYNIMPORT && !ctxt.DynlinkingGo() && !r.Sym.Attr.SubSymbol() {
-			if !(ctxt.Arch.Family == sys.PPC64 && ctxt.LinkMode == LinkExternal && 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(ctxt.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 ctxt.LinkMode == LinkExternal {
-			r.InitExt()
-		}
-
-		// TODO(mundaym): remove this special case - see issue 14218.
-		if ctxt.Arch.Family == sys.S390X {
-			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(ctxt.Arch.ByteOrder.Uint16(s.P[off:]))
-			case 4:
-				o = int64(ctxt.Arch.ByteOrder.Uint32(s.P[off:]))
-			case 8:
-				o = int64(ctxt.Arch.ByteOrder.Uint64(s.P[off:]))
-			}
-			if offset, ok := thearch.Archreloc(ctxt, r, s, o); ok {
-				o = offset
-			} else {
-				Errorf(s, "unknown reloc to %v: %d (%s)", r.Sym.Name, r.Type, sym.RelocName(ctxt.Arch, r.Type))
-			}
-		case objabi.R_TLS_LE:
-			if ctxt.LinkMode == LinkExternal && ctxt.IsELF {
-				r.Done = false
-				if r.Sym == nil {
-					r.Sym = ctxt.Tlsg
-				}
-				r.Xsym = r.Sym
-				r.Xadd = r.Add
-				o = 0
-				if ctxt.Arch.Family != sys.AMD64 {
-					o = r.Add
-				}
-				break
-			}
-
-			if ctxt.IsELF && ctxt.Arch.Family == sys.ARM {
-				// 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 ctxt.IsELF || ctxt.HeadType == objabi.Hplan9 || ctxt.HeadType == objabi.Hdarwin {
-				o = int64(ctxt.Tlsoffset) + r.Add
-			} else if ctxt.HeadType == objabi.Hwindows {
-				o = r.Add
-			} else {
-				log.Fatalf("unexpected R_TLS_LE relocation for %v", ctxt.HeadType)
-			}
-		case objabi.R_TLS_IE:
-			if ctxt.LinkMode == LinkExternal && ctxt.IsELF {
-				r.Done = false
-				if r.Sym == nil {
-					r.Sym = ctxt.Tlsg
-				}
-				r.Xsym = r.Sym
-				r.Xadd = r.Add
-				o = 0
-				if ctxt.Arch.Family != sys.AMD64 {
-					o = r.Add
-				}
-				break
-			}
-			if ctxt.BuildMode == BuildModePIE && ctxt.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", ctxt.Arch.Family)
-				}
-				thearch.TLSIEtoLE(s, int(off), int(r.Siz))
-				o = int64(ctxt.Tlsoffset)
-				// TODO: o += r.Add when ctxt.Arch.Family != sys.AMD64?
-				// 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 ctxt.LinkMode == LinkExternal && 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 ctxt.IsELF {
-					if ctxt.Arch.Family == sys.AMD64 {
-						o = 0
-					}
-				} else if ctxt.HeadType == objabi.Hdarwin {
-					if rs.Type != sym.SHOSTOBJ {
-						o += Symaddr(rs)
-					}
-				} else if ctxt.HeadType == objabi.Hwindows {
-					// nothing to do
-				} else if ctxt.HeadType == objabi.Haix {
-					o = Symaddr(r.Sym) + r.Add
-				} else {
-					Errorf(s, "unhandled pcrel relocation to %s on %v", rs.Name, ctxt.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 ctxt.HeadType == objabi.Haix && 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(ctxt, 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 && ctxt.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 ctxt.LinkMode == LinkExternal {
-				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 ctxt.HeadType == objabi.Hdarwin {
-					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 ctxt.HeadType != objabi.Hwindows {
-					r.Type = objabi.R_ADDR
-				}
-
-				r.Xsym = ctxt.Syms.ROLookup(r.Sym.Sect.Name, 0)
-				r.Xadd = r.Add + Symaddr(r.Sym) - int64(r.Sym.Sect.Vaddr)
-
-				o = r.Xadd
-				if ctxt.IsELF && ctxt.Arch.Family == sys.AMD64 {
-					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(r.Sym.Unit.Textp[0])
-
-			// r->sym can be null when CALL $(constant) is transformed from absolute PC to relative PC call.
-		case objabi.R_GOTPCREL:
-			if ctxt.DynlinkingGo() && ctxt.HeadType == objabi.Hdarwin && 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 ctxt.LinkMode == LinkExternal && r.Sym != nil && r.Sym.Type == sym.SUNDEFEXT {
-				// pass through to the external linker.
-				r.Done = false
-				r.Xadd = 0
-				if ctxt.IsELF {
-					r.Xadd -= int64(r.Siz)
-				}
-				r.Xsym = r.Sym
-				o = 0
-				break
-			}
-			if ctxt.LinkMode == LinkExternal && 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 ctxt.IsELF {
-					if ctxt.Arch.Family == sys.AMD64 {
-						o = 0
-					}
-				} else if ctxt.HeadType == objabi.Hdarwin {
-					if r.Type == objabi.R_CALL {
-						if ctxt.LinkMode == LinkExternal && rs.Type == sym.SDYNIMPORT {
-							if ctxt.Arch.Family == sys.AMD64 {
-								// 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 ctxt.HeadType == objabi.Hwindows && ctxt.Arch.Family == sys.AMD64 { // 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, ctxt.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 ctxt.HeadType != objabi.Haix {
-				Errorf(s, "find XCOFF R_REF on non-XCOFF files")
-			}
-			if ctxt.LinkMode != LinkExternal {
-				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 ctxt.Arch.Family == sys.PPC64 || ctxt.Arch.Family == sys.S390X {
-			r.InitExt()
-			if r.Variant != sym.RV_NONE {
-				o = thearch.Archrelocvariant(ctxt, 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(ctxt.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)
-			ctxt.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)
-			ctxt.Arch.ByteOrder.PutUint32(s.P[off:], uint32(fl))
-		case 8:
-			ctxt.Arch.ByteOrder.PutUint64(s.P[off:], uint64(o))
-		}
-	}
-}
-
-func (ctxt *Link) reloc() {
-	for _, s := range ctxt.Textp {
-		relocsym(ctxt, s)
-	}
-	for _, s := range datap {
-		relocsym(ctxt, s)
-	}
-	for _, s := range dwarfp {
-		relocsym(ctxt, s)
-	}
-}
-
-func windynrelocsym(ctxt *Link, rel, s *sym.Symbol) {
-	for ri := range s.R {
-		r := &s.R[ri]
-		targ := r.Sym
-		if targ == nil {
-			continue
-		}
-		if !targ.Attr.Reachable() {
-			if r.Type == objabi.R_WEAKADDROFF {
-				continue
-			}
-			Errorf(s, "dynamic relocation to unreachable symbol %s", targ.Name)
-		}
-		if r.Sym.Plt() == -2 && r.Sym.Got() != -2 { // make dynimport JMP table for PE object files.
-			targ.SetPlt(int32(rel.Size))
-			r.Sym = rel
-			r.Add = int64(targ.Plt())
-
-			// jmp *addr
-			switch ctxt.Arch.Family {
-			default:
-				Errorf(s, "unsupported arch %v", ctxt.Arch.Family)
-				return
-			case sys.I386:
-				rel.AddUint8(0xff)
-				rel.AddUint8(0x25)
-				rel.AddAddr(ctxt.Arch, targ)
-				rel.AddUint8(0x90)
-				rel.AddUint8(0x90)
-			case sys.AMD64:
-				rel.AddUint8(0xff)
-				rel.AddUint8(0x24)
-				rel.AddUint8(0x25)
-				rel.AddAddrPlus4(targ, 0)
-				rel.AddUint8(0x90)
-			}
-		} else if r.Sym.Plt() >= 0 {
-			r.Sym = rel
-			r.Add = int64(targ.Plt())
-		}
-	}
-}
-
-// windynrelocsyms generates jump table to C library functions that will be
-// added later. windynrelocsyms writes the table into .rel symbol.
-func (ctxt *Link) windynrelocsyms() {
-	if !(ctxt.HeadType == objabi.Hwindows && iscgo && ctxt.LinkMode == LinkInternal) {
-		return
-	}
-
-	/* relocation table */
-	rel := ctxt.Syms.Lookup(".rel", 0)
-	rel.Attr |= sym.AttrReachable
-	rel.Type = sym.STEXT
-	ctxt.Textp = append(ctxt.Textp, rel)
-
-	for _, s := range ctxt.Textp {
-		if s == rel {
-			continue
-		}
-		windynrelocsym(ctxt, rel, s)
-	}
-}
-
-func dynrelocsym(ctxt *Link, s *sym.Symbol) {
-	for ri := range s.R {
-		r := &s.R[ri]
-		if ctxt.BuildMode == BuildModePIE && ctxt.LinkMode == LinkInternal {
-			// It's expected that some relocations will be done
-			// later by relocsym (R_TLS_LE, R_ADDROFF), so
-			// don't worry if Adddynrel returns false.
-			thearch.Adddynrel(ctxt, s, r)
-			continue
-		}
-
-		if r.Sym != nil && r.Sym.Type == sym.SDYNIMPORT || r.Type >= objabi.ElfRelocOffset {
-			if r.Sym != nil && !r.Sym.Attr.Reachable() {
-				Errorf(s, "dynamic relocation to unreachable symbol %s", r.Sym.Name)
-			}
-			if !thearch.Adddynrel(ctxt, s, r) {
-				Errorf(s, "unsupported dynamic relocation for symbol %s (type=%d (%s) stype=%d (%s))", r.Sym.Name, r.Type, sym.RelocName(ctxt.Arch, r.Type), r.Sym.Type, r.Sym.Type)
-			}
-		}
-	}
-}
-
-func dynreloc(ctxt *Link, data *[sym.SXREF][]*sym.Symbol) {
-	if ctxt.HeadType == objabi.Hwindows {
-		return
-	}
-	// -d suppresses dynamic loader format, so we may as well not
-	// compute these sections or mark their symbols as reachable.
-	if *FlagD {
-		return
-	}
-
-	for _, s := range ctxt.Textp {
-		dynrelocsym(ctxt, s)
-	}
-	for _, syms := range data {
-		for _, s := range syms {
-			dynrelocsym(ctxt, s)
-		}
-	}
-	if ctxt.IsELF {
-		elfdynhash(ctxt)
-	}
-}
-
-func Codeblk(ctxt *Link, addr int64, size int64) {
-	CodeblkPad(ctxt, addr, size, zeros[:])
-}
-func CodeblkPad(ctxt *Link, addr int64, size int64, pad []byte) {
-	if *flagA {
-		ctxt.Logf("codeblk [%#x,%#x) at offset %#x\n", addr, addr+size, ctxt.Out.Offset())
-	}
-
-	blk(ctxt.Out, ctxt.Textp, addr, size, pad)
-
-	/* again for printing */
-	if !*flagA {
-		return
-	}
-
-	syms := ctxt.Textp
-	for i, s := range syms {
-		if !s.Attr.Reachable() {
-			continue
-		}
-		if s.Value >= addr {
-			syms = syms[i:]
-			break
-		}
-	}
-
-	eaddr := addr + size
-	for _, s := range syms {
-		if !s.Attr.Reachable() {
-			continue
-		}
-		if s.Value >= eaddr {
-			break
-		}
-
-		if addr < s.Value {
-			ctxt.Logf("%-20s %.8x|", "_", uint64(addr))
-			for ; addr < s.Value; addr++ {
-				ctxt.Logf(" %.2x", 0)
-			}
-			ctxt.Logf("\n")
-		}
-
-		ctxt.Logf("%.6x\t%-20s\n", uint64(addr), s.Name)
-		q := s.P
-
-		for len(q) >= 16 {
-			ctxt.Logf("%.6x\t% x\n", uint64(addr), q[:16])
-			addr += 16
-			q = q[16:]
-		}
-
-		if len(q) > 0 {
-			ctxt.Logf("%.6x\t% x\n", uint64(addr), q)
-			addr += int64(len(q))
-		}
-	}
-
-	if addr < eaddr {
-		ctxt.Logf("%-20s %.8x|", "_", uint64(addr))
-		for ; addr < eaddr; addr++ {
-			ctxt.Logf(" %.2x", 0)
-		}
-	}
-}
-
-func blk(out *OutBuf, syms []*sym.Symbol, addr, size int64, pad []byte) {
-	for i, s := range syms {
-		if !s.Attr.SubSymbol() && s.Value >= addr {
-			syms = syms[i:]
-			break
-		}
-	}
-
-	// This doesn't distinguish the memory size from the file
-	// size, and it lays out the file based on Symbol.Value, which
-	// is the virtual address. DWARF compression changes file sizes,
-	// so dwarfcompress will fix this up later if necessary.
-	eaddr := addr + size
-	for _, s := range syms {
-		if s.Attr.SubSymbol() {
-			continue
-		}
-		if s.Value >= eaddr {
-			break
-		}
-		if s.Value < addr {
-			Errorf(s, "phase error: addr=%#x but sym=%#x type=%d", addr, s.Value, s.Type)
-			errorexit()
-		}
-		if addr < s.Value {
-			out.WriteStringPad("", int(s.Value-addr), pad)
-			addr = s.Value
-		}
-		out.WriteSym(s)
-		addr += int64(len(s.P))
-		if addr < s.Value+s.Size {
-			out.WriteStringPad("", int(s.Value+s.Size-addr), pad)
-			addr = s.Value + s.Size
-		}
-		if addr != s.Value+s.Size {
-			Errorf(s, "phase error: addr=%#x value+size=%#x", addr, s.Value+s.Size)
-			errorexit()
-		}
-		if s.Value+s.Size >= eaddr {
-			break
-		}
-	}
-
-	if addr < eaddr {
-		out.WriteStringPad("", int(eaddr-addr), pad)
-	}
-	out.Flush()
-}
-
-func Datblk(ctxt *Link, addr int64, size int64) {
-	writeDatblkToOutBuf(ctxt, ctxt.Out, addr, size)
-}
-
-// Used only on Wasm for now.
-func DatblkBytes(ctxt *Link, addr int64, size int64) []byte {
-	buf := bytes.NewBuffer(make([]byte, 0, size))
-	out := &OutBuf{w: bufio.NewWriter(buf)}
-	writeDatblkToOutBuf(ctxt, out, addr, size)
-	out.Flush()
-	return buf.Bytes()
-}
-
-func writeDatblkToOutBuf(ctxt *Link, out *OutBuf, addr int64, size int64) {
-	if *flagA {
-		ctxt.Logf("datblk [%#x,%#x) at offset %#x\n", addr, addr+size, ctxt.Out.Offset())
-	}
-
-	blk(out, datap, addr, size, zeros[:])
-
-	/* again for printing */
-	if !*flagA {
-		return
-	}
-
-	syms := datap
-	for i, sym := range syms {
-		if sym.Value >= addr {
-			syms = syms[i:]
-			break
-		}
-	}
-
-	eaddr := addr + size
-	for _, sym := range syms {
-		if sym.Value >= eaddr {
-			break
-		}
-		if addr < sym.Value {
-			ctxt.Logf("\t%.8x| 00 ...\n", uint64(addr))
-			addr = sym.Value
-		}
-
-		ctxt.Logf("%s\n\t%.8x|", sym.Name, uint64(addr))
-		for i, b := range sym.P {
-			if i > 0 && i%16 == 0 {
-				ctxt.Logf("\n\t%.8x|", uint64(addr)+uint64(i))
-			}
-			ctxt.Logf(" %.2x", b)
-		}
-
-		addr += int64(len(sym.P))
-		for ; addr < sym.Value+sym.Size; addr++ {
-			ctxt.Logf(" %.2x", 0)
-		}
-		ctxt.Logf("\n")
-
-		if ctxt.LinkMode != LinkExternal {
-			continue
-		}
-		for i := range sym.R {
-			r := &sym.R[i] // Copying sym.Reloc has measurable impact on performance
-			rsname := ""
-			rsval := int64(0)
-			if r.Sym != nil {
-				rsname = r.Sym.Name
-				rsval = r.Sym.Value
-			}
-			typ := "?"
-			switch r.Type {
-			case objabi.R_ADDR:
-				typ = "addr"
-			case objabi.R_PCREL:
-				typ = "pcrel"
-			case objabi.R_CALL:
-				typ = "call"
-			}
-			ctxt.Logf("\treloc %.8x/%d %s %s+%#x [%#x]\n", uint(sym.Value+int64(r.Off)), r.Siz, typ, rsname, r.Add, rsval+r.Add)
-		}
-	}
-
-	if addr < eaddr {
-		ctxt.Logf("\t%.8x| 00 ...\n", uint(addr))
-	}
-	ctxt.Logf("\t%.8x|\n", uint(eaddr))
-}
-
-func Dwarfblk(ctxt *Link, addr int64, size int64) {
-	if *flagA {
-		ctxt.Logf("dwarfblk [%#x,%#x) at offset %#x\n", addr, addr+size, ctxt.Out.Offset())
-	}
-
-	blk(ctxt.Out, dwarfp, addr, size, zeros[:])
-}
-
-var zeros [512]byte
-
-var (
-	strdata  = make(map[string]string)
-	strnames []string
-)
-
-func addstrdata1(ctxt *Link, arg string) {
-	eq := strings.Index(arg, "=")
-	dot := strings.LastIndex(arg[:eq+1], ".")
-	if eq < 0 || dot < 0 {
-		Exitf("-X flag requires argument of the form importpath.name=value")
-	}
-	pkg := arg[:dot]
-	if ctxt.BuildMode == BuildModePlugin && pkg == "main" {
-		pkg = *flagPluginPath
-	}
-	pkg = objabi.PathToPrefix(pkg)
-	name := pkg + arg[dot:eq]
-	value := arg[eq+1:]
-	if _, ok := strdata[name]; !ok {
-		strnames = append(strnames, name)
-	}
-	strdata[name] = value
-}
-
-// addstrdata sets the initial value of the string variable name to value.
-func addstrdata(ctxt *Link, name, value string) {
-	s := ctxt.Syms.ROLookup(name, 0)
-	if s == nil || s.Gotype == nil {
-		// Not defined in the loaded packages.
-		return
-	}
-	if s.Gotype.Name != "type.string" {
-		Errorf(s, "cannot set with -X: not a var of type string (%s)", s.Gotype.Name)
-		return
-	}
-	if s.Type == sym.SBSS {
-		s.Type = sym.SDATA
-	}
-
-	p := fmt.Sprintf("%s.str", s.Name)
-	sp := ctxt.Syms.Lookup(p, 0)
-
-	Addstring(sp, value)
-	sp.Type = sym.SRODATA
-
-	s.Size = 0
-	s.P = s.P[:0]
-	if s.Attr.ReadOnly() {
-		s.P = make([]byte, 0, ctxt.Arch.PtrSize*2)
-		s.Attr.Set(sym.AttrReadOnly, false)
-	}
-	s.R = s.R[:0]
-	reachable := s.Attr.Reachable()
-	s.AddAddr(ctxt.Arch, sp)
-	s.AddUint(ctxt.Arch, uint64(len(value)))
-
-	// addstring, addaddr, etc., mark the symbols as reachable.
-	// In this case that is not necessarily true, so stick to what
-	// we know before entering this function.
-	s.Attr.Set(sym.AttrReachable, reachable)
-
-	sp.Attr.Set(sym.AttrReachable, reachable)
-}
-
-func (ctxt *Link) dostrdata() {
-	for _, name := range strnames {
-		addstrdata(ctxt, name, strdata[name])
-	}
-}
-
-func Addstring(s *sym.Symbol, str string) int64 {
-	if s.Type == 0 {
-		s.Type = sym.SNOPTRDATA
-	}
-	s.Attr |= sym.AttrReachable
-	r := s.Size
-	if s.Name == ".shstrtab" {
-		elfsetstring(s, str, int(r))
-	}
-	s.P = append(s.P, str...)
-	s.P = append(s.P, 0)
-	s.Size = int64(len(s.P))
-	return r
-}
-
-// addgostring adds str, as a Go string value, to s. symname is the name of the
-// symbol used to define the string data and must be unique per linked object.
-func addgostring(ctxt *Link, s *sym.Symbol, symname, str string) {
-	sdata := ctxt.Syms.Lookup(symname, 0)
-	if sdata.Type != sym.Sxxx {
-		Errorf(s, "duplicate symname in addgostring: %s", symname)
-	}
-	sdata.Attr |= sym.AttrReachable
-	sdata.Attr |= sym.AttrLocal
-	sdata.Type = sym.SRODATA
-	sdata.Size = int64(len(str))
-	sdata.P = []byte(str)
-	s.AddAddr(ctxt.Arch, sdata)
-	s.AddUint(ctxt.Arch, uint64(len(str)))
-}
-
-func addinitarrdata(ctxt *Link, s *sym.Symbol) {
-	p := s.Name + ".ptr"
-	sp := ctxt.Syms.Lookup(p, 0)
-	sp.Type = sym.SINITARR
-	sp.Size = 0
-	sp.Attr |= sym.AttrDuplicateOK
-	sp.AddAddr(ctxt.Arch, s)
-}
-
-// symalign returns the required alignment for the given symbol s.
-func symalign(s *sym.Symbol) int32 {
-	min := int32(thearch.Minalign)
-	if s.Align >= min {
-		return s.Align
-	} else if s.Align != 0 {
-		return min
-	}
-	if strings.HasPrefix(s.Name, "go.string.") || strings.HasPrefix(s.Name, "type..namedata.") {
-		// String data is just bytes.
-		// If we align it, we waste a lot of space to padding.
-		return min
-	}
-	align := int32(thearch.Maxalign)
-	for int64(align) > s.Size && align > min {
-		align >>= 1
-	}
-	s.Align = align
-	return align
-}
-
-func aligndatsize(datsize int64, s *sym.Symbol) int64 {
-	return Rnd(datsize, int64(symalign(s)))
-}
-
-const debugGCProg = false
-
-type GCProg struct {
-	ctxt *Link
-	sym  *sym.Symbol
-	w    gcprog.Writer
-}
-
-func (p *GCProg) Init(ctxt *Link, name string) {
-	p.ctxt = ctxt
-	p.sym = ctxt.Syms.Lookup(name, 0)
-	p.w.Init(p.writeByte(ctxt))
-	if debugGCProg {
-		fmt.Fprintf(os.Stderr, "ld: start GCProg %s\n", name)
-		p.w.Debug(os.Stderr)
-	}
-}
-
-func (p *GCProg) writeByte(ctxt *Link) func(x byte) {
-	return func(x byte) {
-		p.sym.AddUint8(x)
-	}
-}
-
-func (p *GCProg) End(size int64) {
-	p.w.ZeroUntil(size / int64(p.ctxt.Arch.PtrSize))
-	p.w.End()
-	if debugGCProg {
-		fmt.Fprintf(os.Stderr, "ld: end GCProg\n")
-	}
-}
-
-func (p *GCProg) AddSym(s *sym.Symbol) {
-	typ := s.Gotype
-	// Things without pointers should be in sym.SNOPTRDATA or sym.SNOPTRBSS;
-	// everything we see should have pointers and should therefore have a type.
-	if typ == nil {
-		switch s.Name {
-		case "runtime.data", "runtime.edata", "runtime.bss", "runtime.ebss":
-			// Ignore special symbols that are sometimes laid out
-			// as real symbols. See comment about dyld on darwin in
-			// the address function.
-			return
-		}
-		Errorf(s, "missing Go type information for global symbol: size %d", s.Size)
-		return
-	}
-
-	ptrsize := int64(p.ctxt.Arch.PtrSize)
-	nptr := decodetypePtrdata(p.ctxt.Arch, typ.P) / ptrsize
-
-	if debugGCProg {
-		fmt.Fprintf(os.Stderr, "gcprog sym: %s at %d (ptr=%d+%d)\n", s.Name, s.Value, s.Value/ptrsize, nptr)
-	}
-
-	if decodetypeUsegcprog(p.ctxt.Arch, typ.P) == 0 {
-		// Copy pointers from mask into program.
-		mask := decodetypeGcmask(p.ctxt, typ)
-		for i := int64(0); i < nptr; i++ {
-			if (mask[i/8]>>uint(i%8))&1 != 0 {
-				p.w.Ptr(s.Value/ptrsize + i)
-			}
-		}
-		return
-	}
-
-	// Copy program.
-	prog := decodetypeGcprog(p.ctxt, typ)
-	p.w.ZeroUntil(s.Value / ptrsize)
-	p.w.Append(prog[4:], nptr)
-}
-
-// dataSortKey is used to sort a slice of data symbol *sym.Symbol pointers.
-// The sort keys are kept inline to improve cache behavior while sorting.
-type dataSortKey struct {
-	size int64
-	name string
-	sym  *sym.Symbol
-}
-
-type bySizeAndName []dataSortKey
-
-func (d bySizeAndName) Len() int      { return len(d) }
-func (d bySizeAndName) Swap(i, j int) { d[i], d[j] = d[j], d[i] }
-func (d bySizeAndName) Less(i, j int) bool {
-	s1, s2 := d[i], d[j]
-	if s1.size != s2.size {
-		return s1.size < s2.size
-	}
-	return s1.name < s2.name
-}
-
-// cutoff is the maximum data section size permitted by the linker
-// (see issue #9862).
-const cutoff = 2e9 // 2 GB (or so; looks better in errors than 2^31)
-
-func checkdatsize(ctxt *Link, datsize int64, symn sym.SymKind) {
-	if datsize > cutoff {
-		Errorf(nil, "too much data in section %v (over %v bytes)", symn, cutoff)
-	}
-}
-
-// datap is a collection of reachable data symbols in address order.
-// Generated by dodata.
-var datap []*sym.Symbol
-
-func (ctxt *Link) dodata() {
-	if (ctxt.DynlinkingGo() && ctxt.HeadType == objabi.Hdarwin) || (ctxt.HeadType == objabi.Haix && ctxt.LinkMode == LinkExternal) {
-		// The values in moduledata are filled out by relocations
-		// pointing to the addresses of these special symbols.
-		// Typically these symbols have no size and are not laid
-		// out with their matching section.
-		//
-		// However on darwin, dyld will find the special symbol
-		// in the first loaded module, even though it is local.
-		//
-		// (An hypothesis, formed without looking in the dyld sources:
-		// these special symbols have no size, so their address
-		// matches a real symbol. The dynamic linker assumes we
-		// want the normal symbol with the same address and finds
-		// it in the other module.)
-		//
-		// To work around this we lay out the symbls whose
-		// addresses are vital for multi-module programs to work
-		// as normal symbols, and give them a little size.
-		//
-		// On AIX, as all DATA sections are merged together, ld might not put
-		// these symbols at the beginning of their respective section if there
-		// aren't real symbols, their alignment might not match the
-		// first symbol alignment. Therefore, there are explicitly put at the
-		// beginning of their section with the same alignment.
-		bss := ctxt.Syms.Lookup("runtime.bss", 0)
-		bss.Size = 8
-		bss.Attr.Set(sym.AttrSpecial, false)
-
-		ctxt.Syms.Lookup("runtime.ebss", 0).Attr.Set(sym.AttrSpecial, false)
-
-		data := ctxt.Syms.Lookup("runtime.data", 0)
-		data.Size = 8
-		data.Attr.Set(sym.AttrSpecial, false)
-
-		edata := ctxt.Syms.Lookup("runtime.edata", 0)
-		edata.Attr.Set(sym.AttrSpecial, false)
-		if ctxt.HeadType == objabi.Haix {
-			// XCOFFTOC symbols are part of .data section.
-			edata.Type = sym.SXCOFFTOC
-		}
-
-		types := ctxt.Syms.Lookup("runtime.types", 0)
-		types.Type = sym.STYPE
-		types.Size = 8
-		types.Attr.Set(sym.AttrSpecial, false)
-
-		etypes := ctxt.Syms.Lookup("runtime.etypes", 0)
-		etypes.Type = sym.SFUNCTAB
-		etypes.Attr.Set(sym.AttrSpecial, false)
-
-		if ctxt.HeadType == objabi.Haix {
-			rodata := ctxt.Syms.Lookup("runtime.rodata", 0)
-			rodata.Type = sym.SSTRING
-			rodata.Size = 8
-			rodata.Attr.Set(sym.AttrSpecial, false)
-
-			ctxt.Syms.Lookup("runtime.erodata", 0).Attr.Set(sym.AttrSpecial, false)
-
-		}
-	}
-
-	// Collect data symbols by type into data.
-	var data [sym.SXREF][]*sym.Symbol
-	for _, s := range ctxt.Syms.Allsym {
-		if !s.Attr.Reachable() || s.Attr.Special() || s.Attr.SubSymbol() {
-			continue
-		}
-		if s.Type <= sym.STEXT || s.Type >= sym.SXREF {
-			continue
-		}
-		data[s.Type] = append(data[s.Type], s)
-	}
-
-	// Now that we have the data symbols, but before we start
-	// to assign addresses, record all the necessary
-	// dynamic relocations. These will grow the relocation
-	// symbol, which is itself data.
-	//
-	// On darwin, we need the symbol table numbers for dynreloc.
-	if ctxt.HeadType == objabi.Hdarwin {
-		machosymorder(ctxt)
-	}
-	dynreloc(ctxt, &data)
-
-	if ctxt.UseRelro() {
-		// "read only" data with relocations needs to go in its own section
-		// when building a shared library. We do this by boosting objects of
-		// type SXXX with relocations to type SXXXRELRO.
-		for _, symnro := range sym.ReadOnly {
-			symnrelro := sym.RelROMap[symnro]
-
-			ro := []*sym.Symbol{}
-			relro := data[symnrelro]
-
-			for _, s := range data[symnro] {
-				isRelro := len(s.R) > 0
-				switch s.Type {
-				case sym.STYPE, sym.STYPERELRO, sym.SGOFUNCRELRO:
-					// Symbols are not sorted yet, so it is possible
-					// that an Outer symbol has been changed to a
-					// relro Type before it reaches here.
-					isRelro = true
-				case sym.SFUNCTAB:
-					if ctxt.HeadType == objabi.Haix && s.Name == "runtime.etypes" {
-						// runtime.etypes must be at the end of
-						// the relro datas.
-						isRelro = true
-					}
-				}
-				if isRelro {
-					s.Type = symnrelro
-					if s.Outer != nil {
-						s.Outer.Type = s.Type
-					}
-					relro = append(relro, s)
-				} else {
-					ro = append(ro, s)
-				}
-			}
-
-			// Check that we haven't made two symbols with the same .Outer into
-			// different types (because references two symbols with non-nil Outer
-			// become references to the outer symbol + offset it's vital that the
-			// symbol and the outer end up in the same section).
-			for _, s := range relro {
-				if s.Outer != nil && s.Outer.Type != s.Type {
-					Errorf(s, "inconsistent types for symbol and its Outer %s (%v != %v)",
-						s.Outer.Name, s.Type, s.Outer.Type)
-				}
-			}
-
-			data[symnro] = ro
-			data[symnrelro] = relro
-		}
-	}
-
-	// Sort symbols.
-	var dataMaxAlign [sym.SXREF]int32
-	var wg sync.WaitGroup
-	for symn := range data {
-		symn := sym.SymKind(symn)
-		wg.Add(1)
-		go func() {
-			data[symn], dataMaxAlign[symn] = dodataSect(ctxt, symn, data[symn])
-			wg.Done()
-		}()
-	}
-	wg.Wait()
-
-	if ctxt.HeadType == objabi.Haix && ctxt.LinkMode == LinkExternal {
-		// These symbols must have the same alignment as their section.
-		// Otherwize, ld might change the layout of Go sections.
-		ctxt.Syms.ROLookup("runtime.data", 0).Align = dataMaxAlign[sym.SDATA]
-		ctxt.Syms.ROLookup("runtime.bss", 0).Align = dataMaxAlign[sym.SBSS]
-	}
-
-	// Allocate sections.
-	// Data is processed before segtext, because we need
-	// to see all symbols in the .data and .bss sections in order
-	// to generate garbage collection information.
-	datsize := int64(0)
-
-	// Writable data sections that do not need any specialized handling.
-	writable := []sym.SymKind{
-		sym.SBUILDINFO,
-		sym.SELFSECT,
-		sym.SMACHO,
-		sym.SMACHOGOT,
-		sym.SWINDOWS,
-	}
-	for _, symn := range writable {
-		for _, s := range data[symn] {
-			sect := addsection(ctxt.Arch, &Segdata, s.Name, 06)
-			sect.Align = symalign(s)
-			datsize = Rnd(datsize, int64(sect.Align))
-			sect.Vaddr = uint64(datsize)
-			s.Sect = sect
-			s.Type = sym.SDATA
-			s.Value = int64(uint64(datsize) - sect.Vaddr)
-			datsize += s.Size
-			sect.Length = uint64(datsize) - sect.Vaddr
-		}
-		checkdatsize(ctxt, datsize, symn)
-	}
-
-	// .got (and .toc on ppc64)
-	if len(data[sym.SELFGOT]) > 0 {
-		sect := addsection(ctxt.Arch, &Segdata, ".got", 06)
-		sect.Align = dataMaxAlign[sym.SELFGOT]
-		datsize = Rnd(datsize, int64(sect.Align))
-		sect.Vaddr = uint64(datsize)
-		for _, s := range data[sym.SELFGOT] {
-			datsize = aligndatsize(datsize, s)
-			s.Sect = sect
-			s.Type = sym.SDATA
-			s.Value = int64(uint64(datsize) - sect.Vaddr)
-
-			// Resolve .TOC. symbol for this object file (ppc64)
-			toc := ctxt.Syms.ROLookup(".TOC.", int(s.Version))
-			if toc != nil {
-				toc.Sect = sect
-				toc.Outer = s
-				toc.Sub = s.Sub
-				s.Sub = toc
-
-				toc.Value = 0x8000
-			}
-
-			datsize += s.Size
-		}
-		checkdatsize(ctxt, datsize, sym.SELFGOT)
-		sect.Length = uint64(datsize) - sect.Vaddr
-	}
-
-	/* pointer-free data */
-	sect := addsection(ctxt.Arch, &Segdata, ".noptrdata", 06)
-	sect.Align = dataMaxAlign[sym.SNOPTRDATA]
-	datsize = Rnd(datsize, int64(sect.Align))
-	sect.Vaddr = uint64(datsize)
-	ctxt.Syms.Lookup("runtime.noptrdata", 0).Sect = sect
-	ctxt.Syms.Lookup("runtime.enoptrdata", 0).Sect = sect
-	for _, s := range data[sym.SNOPTRDATA] {
-		datsize = aligndatsize(datsize, s)
-		s.Sect = sect
-		s.Type = sym.SDATA
-		s.Value = int64(uint64(datsize) - sect.Vaddr)
-		datsize += s.Size
-	}
-	checkdatsize(ctxt, datsize, sym.SNOPTRDATA)
-	sect.Length = uint64(datsize) - sect.Vaddr
-
-	hasinitarr := ctxt.linkShared
-
-	/* shared library initializer */
-	switch ctxt.BuildMode {
-	case BuildModeCArchive, BuildModeCShared, BuildModeShared, BuildModePlugin:
-		hasinitarr = true
-	}
-
-	if ctxt.HeadType == objabi.Haix {
-		if len(data[sym.SINITARR]) > 0 {
-			Errorf(nil, "XCOFF format doesn't allow .init_array section")
-		}
-	}
-
-	if hasinitarr && len(data[sym.SINITARR]) > 0 {
-		sect := addsection(ctxt.Arch, &Segdata, ".init_array", 06)
-		sect.Align = dataMaxAlign[sym.SINITARR]
-		datsize = Rnd(datsize, int64(sect.Align))
-		sect.Vaddr = uint64(datsize)
-		for _, s := range data[sym.SINITARR] {
-			datsize = aligndatsize(datsize, s)
-			s.Sect = sect
-			s.Value = int64(uint64(datsize) - sect.Vaddr)
-			datsize += s.Size
-		}
-		sect.Length = uint64(datsize) - sect.Vaddr
-		checkdatsize(ctxt, datsize, sym.SINITARR)
-	}
-
-	/* data */
-	sect = addsection(ctxt.Arch, &Segdata, ".data", 06)
-	sect.Align = dataMaxAlign[sym.SDATA]
-	datsize = Rnd(datsize, int64(sect.Align))
-	sect.Vaddr = uint64(datsize)
-	ctxt.Syms.Lookup("runtime.data", 0).Sect = sect
-	ctxt.Syms.Lookup("runtime.edata", 0).Sect = sect
-	var gc GCProg
-	gc.Init(ctxt, "runtime.gcdata")
-	for _, s := range data[sym.SDATA] {
-		s.Sect = sect
-		s.Type = sym.SDATA
-		datsize = aligndatsize(datsize, s)
-		s.Value = int64(uint64(datsize) - sect.Vaddr)
-		gc.AddSym(s)
-		datsize += s.Size
-	}
-	gc.End(datsize - int64(sect.Vaddr))
-	// On AIX, TOC entries must be the last of .data
-	// These aren't part of gc as they won't change during the runtime.
-	for _, s := range data[sym.SXCOFFTOC] {
-		s.Sect = sect
-		s.Type = sym.SDATA
-		datsize = aligndatsize(datsize, s)
-		s.Value = int64(uint64(datsize) - sect.Vaddr)
-		datsize += s.Size
-	}
-	checkdatsize(ctxt, datsize, sym.SDATA)
-	sect.Length = uint64(datsize) - sect.Vaddr
-
-	/* bss */
-	sect = addsection(ctxt.Arch, &Segdata, ".bss", 06)
-	sect.Align = dataMaxAlign[sym.SBSS]
-	datsize = Rnd(datsize, int64(sect.Align))
-	sect.Vaddr = uint64(datsize)
-	ctxt.Syms.Lookup("runtime.bss", 0).Sect = sect
-	ctxt.Syms.Lookup("runtime.ebss", 0).Sect = sect
-	gc = GCProg{}
-	gc.Init(ctxt, "runtime.gcbss")
-	for _, s := range data[sym.SBSS] {
-		s.Sect = sect
-		datsize = aligndatsize(datsize, s)
-		s.Value = int64(uint64(datsize) - sect.Vaddr)
-		gc.AddSym(s)
-		datsize += s.Size
-	}
-	checkdatsize(ctxt, datsize, sym.SBSS)
-	sect.Length = uint64(datsize) - sect.Vaddr
-	gc.End(int64(sect.Length))
-
-	/* pointer-free bss */
-	sect = addsection(ctxt.Arch, &Segdata, ".noptrbss", 06)
-	sect.Align = dataMaxAlign[sym.SNOPTRBSS]
-	datsize = Rnd(datsize, int64(sect.Align))
-	sect.Vaddr = uint64(datsize)
-	ctxt.Syms.Lookup("runtime.noptrbss", 0).Sect = sect
-	ctxt.Syms.Lookup("runtime.enoptrbss", 0).Sect = sect
-	for _, s := range data[sym.SNOPTRBSS] {
-		datsize = aligndatsize(datsize, s)
-		s.Sect = sect
-		s.Value = int64(uint64(datsize) - sect.Vaddr)
-		datsize += s.Size
-	}
-	sect.Length = uint64(datsize) - sect.Vaddr
-	ctxt.Syms.Lookup("runtime.end", 0).Sect = sect
-	checkdatsize(ctxt, datsize, sym.SNOPTRBSS)
-
-	// Coverage instrumentation counters for libfuzzer.
-	if len(data[sym.SLIBFUZZER_EXTRA_COUNTER]) > 0 {
-		sect := addsection(ctxt.Arch, &Segdata, "__libfuzzer_extra_counters", 06)
-		sect.Align = dataMaxAlign[sym.SLIBFUZZER_EXTRA_COUNTER]
-		datsize = Rnd(datsize, int64(sect.Align))
-		sect.Vaddr = uint64(datsize)
-		for _, s := range data[sym.SLIBFUZZER_EXTRA_COUNTER] {
-			datsize = aligndatsize(datsize, s)
-			s.Sect = sect
-			s.Value = int64(uint64(datsize) - sect.Vaddr)
-			datsize += s.Size
-		}
-		sect.Length = uint64(datsize) - sect.Vaddr
-		checkdatsize(ctxt, datsize, sym.SLIBFUZZER_EXTRA_COUNTER)
-	}
-
-	if len(data[sym.STLSBSS]) > 0 {
-		var sect *sym.Section
-		if (ctxt.IsELF || ctxt.HeadType == objabi.Haix) && (ctxt.LinkMode == LinkExternal || !*FlagD) {
-			sect = addsection(ctxt.Arch, &Segdata, ".tbss", 06)
-			sect.Align = int32(ctxt.Arch.PtrSize)
-			sect.Vaddr = 0
-		}
-		datsize = 0
-
-		for _, s := range data[sym.STLSBSS] {
-			datsize = aligndatsize(datsize, s)
-			s.Sect = sect
-			s.Value = datsize
-			datsize += s.Size
-		}
-		checkdatsize(ctxt, datsize, sym.STLSBSS)
-
-		if sect != nil {
-			sect.Length = uint64(datsize)
-		}
-	}
-
-	/*
-	 * We finished data, begin read-only data.
-	 * Not all systems support a separate read-only non-executable data section.
-	 * ELF and Windows PE systems do.
-	 * OS X and Plan 9 do not.
-	 * And if we're using external linking mode, the point is moot,
-	 * since it's not our decision; that code expects the sections in
-	 * segtext.
-	 */
-	var segro *sym.Segment
-	if ctxt.IsELF && ctxt.LinkMode == LinkInternal {
-		segro = &Segrodata
-	} else if ctxt.HeadType == objabi.Hwindows {
-		segro = &Segrodata
-	} else {
-		segro = &Segtext
-	}
-
-	datsize = 0
-
-	/* read-only executable ELF, Mach-O sections */
-	if len(data[sym.STEXT]) != 0 {
-		Errorf(nil, "dodata found an sym.STEXT symbol: %s", data[sym.STEXT][0].Name)
-	}
-	for _, s := range data[sym.SELFRXSECT] {
-		sect := addsection(ctxt.Arch, &Segtext, s.Name, 04)
-		sect.Align = symalign(s)
-		datsize = Rnd(datsize, int64(sect.Align))
-		sect.Vaddr = uint64(datsize)
-		s.Sect = sect
-		s.Type = sym.SRODATA
-		s.Value = int64(uint64(datsize) - sect.Vaddr)
-		datsize += s.Size
-		sect.Length = uint64(datsize) - sect.Vaddr
-		checkdatsize(ctxt, datsize, sym.SELFRXSECT)
-	}
-
-	/* read-only data */
-	sect = addsection(ctxt.Arch, segro, ".rodata", 04)
-
-	sect.Vaddr = 0
-	ctxt.Syms.Lookup("runtime.rodata", 0).Sect = sect
-	ctxt.Syms.Lookup("runtime.erodata", 0).Sect = sect
-	if !ctxt.UseRelro() {
-		ctxt.Syms.Lookup("runtime.types", 0).Sect = sect
-		ctxt.Syms.Lookup("runtime.etypes", 0).Sect = sect
-	}
-	for _, symn := range sym.ReadOnly {
-		align := dataMaxAlign[symn]
-		if sect.Align < align {
-			sect.Align = align
-		}
-	}
-	datsize = Rnd(datsize, int64(sect.Align))
-	for _, symn := range sym.ReadOnly {
-		symnStartValue := datsize
-		for _, s := range data[symn] {
-			datsize = aligndatsize(datsize, s)
-			s.Sect = sect
-			s.Type = sym.SRODATA
-			s.Value = int64(uint64(datsize) - sect.Vaddr)
-			datsize += s.Size
-		}
-		checkdatsize(ctxt, datsize, symn)
-		if ctxt.HeadType == objabi.Haix {
-			// Read-only symbols might be wrapped inside their outer
-			// symbol.
-			// XCOFF symbol table needs to know the size of
-			// these outer symbols.
-			xcoffUpdateOuterSize(ctxt, datsize-symnStartValue, symn)
-		}
-	}
-	sect.Length = uint64(datsize) - sect.Vaddr
-
-	/* read-only ELF, Mach-O sections */
-	for _, s := range data[sym.SELFROSECT] {
-		sect = addsection(ctxt.Arch, segro, s.Name, 04)
-		sect.Align = symalign(s)
-		datsize = Rnd(datsize, int64(sect.Align))
-		sect.Vaddr = uint64(datsize)
-		s.Sect = sect
-		s.Type = sym.SRODATA
-		s.Value = int64(uint64(datsize) - sect.Vaddr)
-		datsize += s.Size
-		sect.Length = uint64(datsize) - sect.Vaddr
-	}
-	checkdatsize(ctxt, datsize, sym.SELFROSECT)
-
-	for _, s := range data[sym.SMACHOPLT] {
-		sect = addsection(ctxt.Arch, segro, s.Name, 04)
-		sect.Align = symalign(s)
-		datsize = Rnd(datsize, int64(sect.Align))
-		sect.Vaddr = uint64(datsize)
-		s.Sect = sect
-		s.Type = sym.SRODATA
-		s.Value = int64(uint64(datsize) - sect.Vaddr)
-		datsize += s.Size
-		sect.Length = uint64(datsize) - sect.Vaddr
-	}
-	checkdatsize(ctxt, datsize, sym.SMACHOPLT)
-
-	// There is some data that are conceptually read-only but are written to by
-	// relocations. On GNU systems, we can arrange for the dynamic linker to
-	// mprotect sections after relocations are applied by giving them write
-	// permissions in the object file and calling them ".data.rel.ro.FOO". We
-	// divide the .rodata section between actual .rodata and .data.rel.ro.rodata,
-	// but for the other sections that this applies to, we just write a read-only
-	// .FOO section or a read-write .data.rel.ro.FOO section depending on the
-	// situation.
-	// TODO(mwhudson): It would make sense to do this more widely, but it makes
-	// the system linker segfault on darwin.
-	addrelrosection := func(suffix string) *sym.Section {
-		return addsection(ctxt.Arch, segro, suffix, 04)
-	}
-
-	if ctxt.UseRelro() {
-		segrelro := &Segrelrodata
-		if ctxt.LinkMode == LinkExternal && ctxt.HeadType != objabi.Haix {
-			// Using a separate segment with an external
-			// linker results in some programs moving
-			// their data sections unexpectedly, which
-			// corrupts the moduledata. So we use the
-			// rodata segment and let the external linker
-			// sort out a rel.ro segment.
-			segrelro = segro
-		} else {
-			// Reset datsize for new segment.
-			datsize = 0
-		}
-
-		addrelrosection = func(suffix string) *sym.Section {
-			return addsection(ctxt.Arch, segrelro, ".data.rel.ro"+suffix, 06)
-		}
-
-		/* data only written by relocations */
-		sect = addrelrosection("")
-
-		ctxt.Syms.Lookup("runtime.types", 0).Sect = sect
-		ctxt.Syms.Lookup("runtime.etypes", 0).Sect = sect
-
-		for _, symnro := range sym.ReadOnly {
-			symn := sym.RelROMap[symnro]
-			align := dataMaxAlign[symn]
-			if sect.Align < align {
-				sect.Align = align
-			}
-		}
-		datsize = Rnd(datsize, int64(sect.Align))
-		sect.Vaddr = uint64(datsize)
-
-		for i, symnro := range sym.ReadOnly {
-			if i == 0 && symnro == sym.STYPE && ctxt.HeadType != objabi.Haix {
-				// Skip forward so that no type
-				// reference uses a zero offset.
-				// This is unlikely but possible in small
-				// programs with no other read-only data.
-				datsize++
-			}
-
-			symn := sym.RelROMap[symnro]
-			symnStartValue := datsize
-			for _, s := range data[symn] {
-				datsize = aligndatsize(datsize, s)
-				if s.Outer != nil && s.Outer.Sect != nil && s.Outer.Sect != sect {
-					Errorf(s, "s.Outer (%s) in different section from s, %s != %s", s.Outer.Name, s.Outer.Sect.Name, sect.Name)
-				}
-				s.Sect = sect
-				s.Type = sym.SRODATA
-				s.Value = int64(uint64(datsize) - sect.Vaddr)
-				datsize += s.Size
-			}
-			checkdatsize(ctxt, datsize, symn)
-			if ctxt.HeadType == objabi.Haix {
-				// Read-only symbols might be wrapped inside their outer
-				// symbol.
-				// XCOFF symbol table needs to know the size of
-				// these outer symbols.
-				xcoffUpdateOuterSize(ctxt, datsize-symnStartValue, symn)
-			}
-		}
-
-		sect.Length = uint64(datsize) - sect.Vaddr
-	}
-
-	/* typelink */
-	sect = addrelrosection(".typelink")
-	sect.Align = dataMaxAlign[sym.STYPELINK]
-	datsize = Rnd(datsize, int64(sect.Align))
-	sect.Vaddr = uint64(datsize)
-	typelink := ctxt.Syms.Lookup("runtime.typelink", 0)
-	typelink.Sect = sect
-	typelink.Type = sym.SRODATA
-	datsize += typelink.Size
-	checkdatsize(ctxt, datsize, sym.STYPELINK)
-	sect.Length = uint64(datsize) - sect.Vaddr
-
-	/* itablink */
-	sect = addrelrosection(".itablink")
-	sect.Align = dataMaxAlign[sym.SITABLINK]
-	datsize = Rnd(datsize, int64(sect.Align))
-	sect.Vaddr = uint64(datsize)
-	ctxt.Syms.Lookup("runtime.itablink", 0).Sect = sect
-	ctxt.Syms.Lookup("runtime.eitablink", 0).Sect = sect
-	for _, s := range data[sym.SITABLINK] {
-		datsize = aligndatsize(datsize, s)
-		s.Sect = sect
-		s.Type = sym.SRODATA
-		s.Value = int64(uint64(datsize) - sect.Vaddr)
-		datsize += s.Size
-	}
-	checkdatsize(ctxt, datsize, sym.SITABLINK)
-	sect.Length = uint64(datsize) - sect.Vaddr
-	if ctxt.HeadType == objabi.Haix {
-		// Store .itablink size because its symbols are wrapped
-		// under an outer symbol: runtime.itablink.
-		xcoffUpdateOuterSize(ctxt, int64(sect.Length), sym.SITABLINK)
-	}
-
-	/* gosymtab */
-	sect = addrelrosection(".gosymtab")
-	sect.Align = dataMaxAlign[sym.SSYMTAB]
-	datsize = Rnd(datsize, int64(sect.Align))
-	sect.Vaddr = uint64(datsize)
-	ctxt.Syms.Lookup("runtime.symtab", 0).Sect = sect
-	ctxt.Syms.Lookup("runtime.esymtab", 0).Sect = sect
-	for _, s := range data[sym.SSYMTAB] {
-		datsize = aligndatsize(datsize, s)
-		s.Sect = sect
-		s.Type = sym.SRODATA
-		s.Value = int64(uint64(datsize) - sect.Vaddr)
-		datsize += s.Size
-	}
-	checkdatsize(ctxt, datsize, sym.SSYMTAB)
-	sect.Length = uint64(datsize) - sect.Vaddr
-
-	/* gopclntab */
-	sect = addrelrosection(".gopclntab")
-	sect.Align = dataMaxAlign[sym.SPCLNTAB]
-	datsize = Rnd(datsize, int64(sect.Align))
-	sect.Vaddr = uint64(datsize)
-	ctxt.Syms.Lookup("runtime.pclntab", 0).Sect = sect
-	ctxt.Syms.Lookup("runtime.epclntab", 0).Sect = sect
-	for _, s := range data[sym.SPCLNTAB] {
-		datsize = aligndatsize(datsize, s)
-		s.Sect = sect
-		s.Type = sym.SRODATA
-		s.Value = int64(uint64(datsize) - sect.Vaddr)
-		datsize += s.Size
-	}
-	checkdatsize(ctxt, datsize, sym.SRODATA)
-	sect.Length = uint64(datsize) - sect.Vaddr
-
-	// 6g uses 4-byte relocation offsets, so the entire segment must fit in 32 bits.
-	if datsize != int64(uint32(datsize)) {
-		Errorf(nil, "read-only data segment too large: %d", datsize)
-	}
-
-	for symn := sym.SELFRXSECT; symn < sym.SXREF; symn++ {
-		datap = append(datap, data[symn]...)
-	}
-
-	dwarfGenerateDebugSyms(ctxt)
-
-	var i int
-	for ; i < len(dwarfp); i++ {
-		s := dwarfp[i]
-		if s.Type != sym.SDWARFSECT {
-			break
-		}
-
-		sect = addsection(ctxt.Arch, &Segdwarf, s.Name, 04)
-		sect.Align = 1
-		datsize = Rnd(datsize, int64(sect.Align))
-		sect.Vaddr = uint64(datsize)
-		s.Sect = sect
-		s.Type = sym.SRODATA
-		s.Value = int64(uint64(datsize) - sect.Vaddr)
-		datsize += s.Size
-		sect.Length = uint64(datsize) - sect.Vaddr
-	}
-	checkdatsize(ctxt, datsize, sym.SDWARFSECT)
-
-	for i < len(dwarfp) {
-		curType := dwarfp[i].Type
-		var sect *sym.Section
-		switch curType {
-		case sym.SDWARFINFO:
-			sect = addsection(ctxt.Arch, &Segdwarf, ".debug_info", 04)
-		case sym.SDWARFRANGE:
-			sect = addsection(ctxt.Arch, &Segdwarf, ".debug_ranges", 04)
-		case sym.SDWARFLOC:
-			sect = addsection(ctxt.Arch, &Segdwarf, ".debug_loc", 04)
-		default:
-			// Error is unrecoverable, so panic.
-			panic(fmt.Sprintf("unknown DWARF section %v", curType))
-		}
-
-		sect.Align = 1
-		datsize = Rnd(datsize, int64(sect.Align))
-		sect.Vaddr = uint64(datsize)
-		for ; i < len(dwarfp); i++ {
-			s := dwarfp[i]
-			if s.Type != curType {
-				break
-			}
-			s.Sect = sect
-			s.Type = sym.SRODATA
-			s.Value = int64(uint64(datsize) - sect.Vaddr)
-			s.Attr |= sym.AttrLocal
-			datsize += s.Size
-
-			if ctxt.HeadType == objabi.Haix && curType == sym.SDWARFLOC {
-				// Update the size of .debug_loc for this symbol's
-				// package.
-				addDwsectCUSize(".debug_loc", s.File, uint64(s.Size))
-			}
-		}
-		sect.Length = uint64(datsize) - sect.Vaddr
-		checkdatsize(ctxt, datsize, curType)
-	}
-
-	/* number the sections */
-	n := int32(1)
-
-	for _, sect := range Segtext.Sections {
-		sect.Extnum = int16(n)
-		n++
-	}
-	for _, sect := range Segrodata.Sections {
-		sect.Extnum = int16(n)
-		n++
-	}
-	for _, sect := range Segrelrodata.Sections {
-		sect.Extnum = int16(n)
-		n++
-	}
-	for _, sect := range Segdata.Sections {
-		sect.Extnum = int16(n)
-		n++
-	}
-	for _, sect := range Segdwarf.Sections {
-		sect.Extnum = int16(n)
-		n++
-	}
-}
-
-func dodataSect(ctxt *Link, symn sym.SymKind, syms []*sym.Symbol) (result []*sym.Symbol, maxAlign int32) {
-	if ctxt.HeadType == objabi.Hdarwin {
-		// Some symbols may no longer belong in syms
-		// due to movement in machosymorder.
-		newSyms := make([]*sym.Symbol, 0, len(syms))
-		for _, s := range syms {
-			if s.Type == symn {
-				newSyms = append(newSyms, s)
-			}
-		}
-		syms = newSyms
-	}
-
-	var head, tail *sym.Symbol
-	symsSort := make([]dataSortKey, 0, len(syms))
-	for _, s := range syms {
-		if s.Attr.OnList() {
-			log.Fatalf("symbol %s listed multiple times", s.Name)
-		}
-		s.Attr |= sym.AttrOnList
-		switch {
-		case s.Size < int64(len(s.P)):
-			Errorf(s, "initialize bounds (%d < %d)", s.Size, len(s.P))
-		case s.Size < 0:
-			Errorf(s, "negative size (%d bytes)", s.Size)
-		case s.Size > cutoff:
-			Errorf(s, "symbol too large (%d bytes)", s.Size)
-		}
-
-		// If the usually-special section-marker symbols are being laid
-		// out as regular symbols, put them either at the beginning or
-		// end of their section.
-		if (ctxt.DynlinkingGo() && ctxt.HeadType == objabi.Hdarwin) || (ctxt.HeadType == objabi.Haix && ctxt.LinkMode == LinkExternal) {
-			switch s.Name {
-			case "runtime.text", "runtime.bss", "runtime.data", "runtime.types", "runtime.rodata":
-				head = s
-				continue
-			case "runtime.etext", "runtime.ebss", "runtime.edata", "runtime.etypes", "runtime.erodata":
-				tail = s
-				continue
-			}
-		}
-
-		key := dataSortKey{
-			size: s.Size,
-			name: s.Name,
-			sym:  s,
-		}
-
-		switch s.Type {
-		case sym.SELFGOT:
-			// For ppc64, we want to interleave the .got and .toc sections
-			// from input files. Both are type sym.SELFGOT, so in that case
-			// we skip size comparison and fall through to the name
-			// comparison (conveniently, .got sorts before .toc).
-			key.size = 0
-		}
-
-		symsSort = append(symsSort, key)
-	}
-
-	sort.Sort(bySizeAndName(symsSort))
-
-	off := 0
-	if head != nil {
-		syms[0] = head
-		off++
-	}
-	for i, symSort := range symsSort {
-		syms[i+off] = symSort.sym
-		align := symalign(symSort.sym)
-		if maxAlign < align {
-			maxAlign = align
-		}
-	}
-	if tail != nil {
-		syms[len(syms)-1] = tail
-	}
-
-	if ctxt.IsELF && symn == sym.SELFROSECT {
-		// Make .rela and .rela.plt contiguous, the ELF ABI requires this
-		// and Solaris actually cares.
-		reli, plti := -1, -1
-		for i, s := range syms {
-			switch s.Name {
-			case ".rel.plt", ".rela.plt":
-				plti = i
-			case ".rel", ".rela":
-				reli = i
-			}
-		}
-		if reli >= 0 && plti >= 0 && plti != reli+1 {
-			var first, second int
-			if plti > reli {
-				first, second = reli, plti
-			} else {
-				first, second = plti, reli
-			}
-			rel, plt := syms[reli], syms[plti]
-			copy(syms[first+2:], syms[first+1:second])
-			syms[first+0] = rel
-			syms[first+1] = plt
-
-			// Make sure alignment doesn't introduce a gap.
-			// Setting the alignment explicitly prevents
-			// symalign from basing it on the size and
-			// getting it wrong.
-			rel.Align = int32(ctxt.Arch.RegSize)
-			plt.Align = int32(ctxt.Arch.RegSize)
-		}
-	}
-
-	return syms, maxAlign
-}
-
-// Add buildid to beginning of text segment, on non-ELF systems.
-// Non-ELF binary formats are not always flexible enough to
-// give us a place to put the Go build ID. On those systems, we put it
-// at the very beginning of the text segment.
-// This ``header'' is read by cmd/go.
-func (ctxt *Link) textbuildid() {
-	if ctxt.IsELF || ctxt.BuildMode == BuildModePlugin || *flagBuildid == "" {
-		return
-	}
-
-	s := ctxt.Syms.Lookup("go.buildid", 0)
-	s.Attr |= sym.AttrReachable
-	// The \xff is invalid UTF-8, meant to make it less likely
-	// to find one of these accidentally.
-	data := "\xff Go build ID: " + strconv.Quote(*flagBuildid) + "\n \xff"
-	s.Type = sym.STEXT
-	s.P = []byte(data)
-	s.Size = int64(len(s.P))
-
-	ctxt.Textp = append(ctxt.Textp, nil)
-	copy(ctxt.Textp[1:], ctxt.Textp)
-	ctxt.Textp[0] = s
-}
-
-func (ctxt *Link) buildinfo() {
-	if ctxt.linkShared || ctxt.BuildMode == BuildModePlugin {
-		// -linkshared and -buildmode=plugin get confused
-		// about the relocations in go.buildinfo
-		// pointing at the other data sections.
-		// The version information is only available in executables.
-		return
-	}
-
-	s := ctxt.Syms.Lookup(".go.buildinfo", 0)
-	s.Attr |= sym.AttrReachable
-	s.Type = sym.SBUILDINFO
-	s.Align = 16
-	// The \xff is invalid UTF-8, meant to make it less likely
-	// to find one of these accidentally.
-	const prefix = "\xff Go buildinf:" // 14 bytes, plus 2 data bytes filled in below
-	data := make([]byte, 32)
-	copy(data, prefix)
-	data[len(prefix)] = byte(ctxt.Arch.PtrSize)
-	data[len(prefix)+1] = 0
-	if ctxt.Arch.ByteOrder == binary.BigEndian {
-		data[len(prefix)+1] = 1
-	}
-	s.P = data
-	s.Size = int64(len(s.P))
-	s1 := ctxt.Syms.Lookup("runtime.buildVersion", 0)
-	s2 := ctxt.Syms.Lookup("runtime.modinfo", 0)
-	s.R = []sym.Reloc{
-		{Off: 16, Siz: uint8(ctxt.Arch.PtrSize), Type: objabi.R_ADDR, Sym: s1},
-		{Off: 16 + int32(ctxt.Arch.PtrSize), Siz: uint8(ctxt.Arch.PtrSize), Type: objabi.R_ADDR, Sym: s2},
-	}
-}
-
-// assign addresses to text
-func (ctxt *Link) textaddress() {
-	addsection(ctxt.Arch, &Segtext, ".text", 05)
-
-	// Assign PCs in text segment.
-	// Could parallelize, by assigning to text
-	// and then letting threads copy down, but probably not worth it.
-	sect := Segtext.Sections[0]
-
-	sect.Align = int32(Funcalign)
-
-	text := ctxt.Syms.Lookup("runtime.text", 0)
-	text.Sect = sect
-	if ctxt.HeadType == objabi.Haix && ctxt.LinkMode == LinkExternal {
-		// Setting runtime.text has a real symbol prevents ld to
-		// change its base address resulting in wrong offsets for
-		// reflect methods.
-		text.Align = sect.Align
-		text.Size = 0x8
-	}
-
-	if (ctxt.DynlinkingGo() && ctxt.HeadType == objabi.Hdarwin) || (ctxt.HeadType == objabi.Haix && ctxt.LinkMode == LinkExternal) {
-		etext := ctxt.Syms.Lookup("runtime.etext", 0)
-		etext.Sect = sect
-
-		ctxt.Textp = append(ctxt.Textp, etext, nil)
-		copy(ctxt.Textp[1:], ctxt.Textp)
-		ctxt.Textp[0] = text
-	}
-
-	va := uint64(*FlagTextAddr)
-	n := 1
-	sect.Vaddr = va
-	ntramps := 0
-	for _, s := range ctxt.Textp {
-		sect, n, va = assignAddress(ctxt, sect, n, s, va, false)
-
-		trampoline(ctxt, s) // resolve jumps, may add trampolines if jump too far
-
-		// lay down trampolines after each function
-		for ; ntramps < len(ctxt.tramps); ntramps++ {
-			tramp := ctxt.tramps[ntramps]
-			if ctxt.HeadType == objabi.Haix && strings.HasPrefix(tramp.Name, "runtime.text.") {
-				// Already set in assignAddress
-				continue
-			}
-			sect, n, va = assignAddress(ctxt, sect, n, tramp, va, true)
-		}
-	}
-
-	sect.Length = va - sect.Vaddr
-	ctxt.Syms.Lookup("runtime.etext", 0).Sect = sect
-
-	// merge tramps into Textp, keeping Textp in address order
-	if ntramps != 0 {
-		newtextp := make([]*sym.Symbol, 0, len(ctxt.Textp)+ntramps)
-		i := 0
-		for _, s := range ctxt.Textp {
-			for ; i < ntramps && ctxt.tramps[i].Value < s.Value; i++ {
-				newtextp = append(newtextp, ctxt.tramps[i])
-			}
-			newtextp = append(newtextp, s)
-		}
-		newtextp = append(newtextp, ctxt.tramps[i:ntramps]...)
-
-		ctxt.Textp = newtextp
-	}
-}
-
-// assigns address for a text symbol, returns (possibly new) section, its number, and the address
-// Note: once we have trampoline insertion support for external linking, this function
-// will not need to create new text sections, and so no need to return sect and n.
-func assignAddress(ctxt *Link, sect *sym.Section, n int, s *sym.Symbol, va uint64, isTramp bool) (*sym.Section, int, uint64) {
-	if thearch.AssignAddress != nil {
-		return thearch.AssignAddress(ctxt, sect, n, s, va, isTramp)
-	}
-
-	s.Sect = sect
-	if s.Attr.SubSymbol() {
-		return sect, n, va
-	}
-	if s.Align != 0 {
-		va = uint64(Rnd(int64(va), int64(s.Align)))
-	} else {
-		va = uint64(Rnd(int64(va), int64(Funcalign)))
-	}
-
-	funcsize := uint64(MINFUNC) // spacing required for findfunctab
-	if s.Size > MINFUNC {
-		funcsize = uint64(s.Size)
-	}
-
-	if sect.Align < s.Align {
-		sect.Align = s.Align
-	}
-
-	// On ppc64x a text section should not be larger than 2^26 bytes due to the size of
-	// call target offset field in the bl instruction.  Splitting into smaller text
-	// sections smaller than this limit allows the GNU linker to modify the long calls
-	// appropriately.  The limit allows for the space needed for tables inserted by the linker.
-
-	// If this function doesn't fit in the current text section, then create a new one.
-
-	// Only break at outermost syms.
-
-	if ctxt.Arch.InFamily(sys.PPC64) && s.Outer == nil && ctxt.LinkMode == LinkExternal && va-sect.Vaddr+funcsize+maxSizeTrampolinesPPC64(s, isTramp) > 0x1c00000 {
-		// Set the length for the previous text section
-		sect.Length = va - sect.Vaddr
-
-		// Create new section, set the starting Vaddr
-		sect = addsection(ctxt.Arch, &Segtext, ".text", 05)
-		sect.Vaddr = va
-		s.Sect = sect
-
-		// Create a symbol for the start of the secondary text sections
-		ntext := ctxt.Syms.Lookup(fmt.Sprintf("runtime.text.%d", n), 0)
-		ntext.Sect = sect
-		if ctxt.HeadType == objabi.Haix {
-			// runtime.text.X must be a real symbol on AIX.
-			// Assign its address directly in order to be the
-			// first symbol of this new section.
-			ntext.Type = sym.STEXT
-			ntext.Size = int64(MINFUNC)
-			ntext.Attr |= sym.AttrReachable
-			ntext.Attr |= sym.AttrOnList
-			ctxt.tramps = append(ctxt.tramps, ntext)
-
-			ntext.Value = int64(va)
-			va += uint64(ntext.Size)
-
-			if s.Align != 0 {
-				va = uint64(Rnd(int64(va), int64(s.Align)))
-			} else {
-				va = uint64(Rnd(int64(va), int64(Funcalign)))
-			}
-		}
-		n++
-	}
-
-	s.Value = 0
-	for sub := s; sub != nil; sub = sub.Sub {
-		sub.Value += int64(va)
-	}
-
-	va += funcsize
-
-	return sect, n, va
-}
-
-// address assigns virtual addresses to all segments and sections and
-// returns all segments in file order.
-func (ctxt *Link) address() []*sym.Segment {
-	var order []*sym.Segment // Layout order
-
-	va := uint64(*FlagTextAddr)
-	order = append(order, &Segtext)
-	Segtext.Rwx = 05
-	Segtext.Vaddr = va
-	for _, s := range Segtext.Sections {
-		va = uint64(Rnd(int64(va), int64(s.Align)))
-		s.Vaddr = va
-		va += s.Length
-	}
-
-	Segtext.Length = va - uint64(*FlagTextAddr)
-
-	if len(Segrodata.Sections) > 0 {
-		// align to page boundary so as not to mix
-		// rodata and executable text.
-		//
-		// Note: gold or GNU ld will reduce the size of the executable
-		// file by arranging for the relro segment to end at a page
-		// boundary, and overlap the end of the text segment with the
-		// start of the relro segment in the file.  The PT_LOAD segments
-		// will be such that the last page of the text segment will be
-		// mapped twice, once r-x and once starting out rw- and, after
-		// relocation processing, changed to r--.
-		//
-		// Ideally the last page of the text segment would not be
-		// writable even for this short period.
-		va = uint64(Rnd(int64(va), int64(*FlagRound)))
-
-		order = append(order, &Segrodata)
-		Segrodata.Rwx = 04
-		Segrodata.Vaddr = va
-		for _, s := range Segrodata.Sections {
-			va = uint64(Rnd(int64(va), int64(s.Align)))
-			s.Vaddr = va
-			va += s.Length
-		}
-
-		Segrodata.Length = va - Segrodata.Vaddr
-	}
-	if len(Segrelrodata.Sections) > 0 {
-		// align to page boundary so as not to mix
-		// rodata, rel-ro data, and executable text.
-		va = uint64(Rnd(int64(va), int64(*FlagRound)))
-		if ctxt.HeadType == objabi.Haix {
-			// Relro data are inside data segment on AIX.
-			va += uint64(XCOFFDATABASE) - uint64(XCOFFTEXTBASE)
-		}
-
-		order = append(order, &Segrelrodata)
-		Segrelrodata.Rwx = 06
-		Segrelrodata.Vaddr = va
-		for _, s := range Segrelrodata.Sections {
-			va = uint64(Rnd(int64(va), int64(s.Align)))
-			s.Vaddr = va
-			va += s.Length
-		}
-
-		Segrelrodata.Length = va - Segrelrodata.Vaddr
-	}
-
-	va = uint64(Rnd(int64(va), int64(*FlagRound)))
-	if ctxt.HeadType == objabi.Haix && len(Segrelrodata.Sections) == 0 {
-		// Data sections are moved to an unreachable segment
-		// to ensure that they are position-independent.
-		// Already done if relro sections exist.
-		va += uint64(XCOFFDATABASE) - uint64(XCOFFTEXTBASE)
-	}
-	order = append(order, &Segdata)
-	Segdata.Rwx = 06
-	Segdata.Vaddr = va
-	var data *sym.Section
-	var noptr *sym.Section
-	var bss *sym.Section
-	var noptrbss *sym.Section
-	for i, s := range Segdata.Sections {
-		if (ctxt.IsELF || ctxt.HeadType == objabi.Haix) && s.Name == ".tbss" {
-			continue
-		}
-		vlen := int64(s.Length)
-		if i+1 < len(Segdata.Sections) && !((ctxt.IsELF || ctxt.HeadType == objabi.Haix) && Segdata.Sections[i+1].Name == ".tbss") {
-			vlen = int64(Segdata.Sections[i+1].Vaddr - s.Vaddr)
-		}
-		s.Vaddr = va
-		va += uint64(vlen)
-		Segdata.Length = va - Segdata.Vaddr
-		if s.Name == ".data" {
-			data = s
-		}
-		if s.Name == ".noptrdata" {
-			noptr = s
-		}
-		if s.Name == ".bss" {
-			bss = s
-		}
-		if s.Name == ".noptrbss" {
-			noptrbss = s
-		}
-	}
-
-	// Assign Segdata's Filelen omitting the BSS. We do this here
-	// simply because right now we know where the BSS starts.
-	Segdata.Filelen = bss.Vaddr - Segdata.Vaddr
-
-	va = uint64(Rnd(int64(va), int64(*FlagRound)))
-	order = append(order, &Segdwarf)
-	Segdwarf.Rwx = 06
-	Segdwarf.Vaddr = va
-	for i, s := range Segdwarf.Sections {
-		vlen := int64(s.Length)
-		if i+1 < len(Segdwarf.Sections) {
-			vlen = int64(Segdwarf.Sections[i+1].Vaddr - s.Vaddr)
-		}
-		s.Vaddr = va
-		va += uint64(vlen)
-		if ctxt.HeadType == objabi.Hwindows {
-			va = uint64(Rnd(int64(va), PEFILEALIGN))
-		}
-		Segdwarf.Length = va - Segdwarf.Vaddr
-	}
-
-	var (
-		text     = Segtext.Sections[0]
-		rodata   = ctxt.Syms.Lookup("runtime.rodata", 0).Sect
-		itablink = ctxt.Syms.Lookup("runtime.itablink", 0).Sect
-		symtab   = ctxt.Syms.Lookup("runtime.symtab", 0).Sect
-		pclntab  = ctxt.Syms.Lookup("runtime.pclntab", 0).Sect
-		types    = ctxt.Syms.Lookup("runtime.types", 0).Sect
-	)
-	lasttext := text
-	// Could be multiple .text sections
-	for _, sect := range Segtext.Sections {
-		if sect.Name == ".text" {
-			lasttext = sect
-		}
-	}
-
-	for _, s := range datap {
-		if s.Sect != nil {
-			s.Value += int64(s.Sect.Vaddr)
-		}
-		for sub := s.Sub; sub != nil; sub = sub.Sub {
-			sub.Value += s.Value
-		}
-	}
-
-	for _, s := range dwarfp {
-		if s.Sect != nil {
-			s.Value += int64(s.Sect.Vaddr)
-		}
-		for sub := s.Sub; sub != nil; sub = sub.Sub {
-			sub.Value += s.Value
-		}
-	}
-
-	if ctxt.BuildMode == BuildModeShared {
-		s := ctxt.Syms.Lookup("go.link.abihashbytes", 0)
-		sectSym := ctxt.Syms.Lookup(".note.go.abihash", 0)
-		s.Sect = sectSym.Sect
-		s.Value = int64(sectSym.Sect.Vaddr + 16)
-	}
-
-	ctxt.xdefine("runtime.text", sym.STEXT, int64(text.Vaddr))
-	ctxt.xdefine("runtime.etext", sym.STEXT, int64(lasttext.Vaddr+lasttext.Length))
-
-	// If there are multiple text sections, create runtime.text.n for
-	// their section Vaddr, using n for index
-	n := 1
-	for _, sect := range Segtext.Sections[1:] {
-		if sect.Name != ".text" {
-			break
-		}
-		symname := fmt.Sprintf("runtime.text.%d", n)
-		if ctxt.HeadType != objabi.Haix || ctxt.LinkMode != LinkExternal {
-			// Addresses are already set on AIX with external linker
-			// because these symbols are part of their sections.
-			ctxt.xdefine(symname, sym.STEXT, int64(sect.Vaddr))
-		}
-		n++
-	}
-
-	ctxt.xdefine("runtime.rodata", sym.SRODATA, int64(rodata.Vaddr))
-	ctxt.xdefine("runtime.erodata", sym.SRODATA, int64(rodata.Vaddr+rodata.Length))
-	ctxt.xdefine("runtime.types", sym.SRODATA, int64(types.Vaddr))
-	ctxt.xdefine("runtime.etypes", sym.SRODATA, int64(types.Vaddr+types.Length))
-	ctxt.xdefine("runtime.itablink", sym.SRODATA, int64(itablink.Vaddr))
-	ctxt.xdefine("runtime.eitablink", sym.SRODATA, int64(itablink.Vaddr+itablink.Length))
-
-	s := ctxt.Syms.Lookup("runtime.gcdata", 0)
-	s.Attr |= sym.AttrLocal
-	ctxt.xdefine("runtime.egcdata", sym.SRODATA, Symaddr(s)+s.Size)
-	ctxt.Syms.Lookup("runtime.egcdata", 0).Sect = s.Sect
-
-	s = ctxt.Syms.Lookup("runtime.gcbss", 0)
-	s.Attr |= sym.AttrLocal
-	ctxt.xdefine("runtime.egcbss", sym.SRODATA, Symaddr(s)+s.Size)
-	ctxt.Syms.Lookup("runtime.egcbss", 0).Sect = s.Sect
-
-	ctxt.xdefine("runtime.symtab", sym.SRODATA, int64(symtab.Vaddr))
-	ctxt.xdefine("runtime.esymtab", sym.SRODATA, int64(symtab.Vaddr+symtab.Length))
-	ctxt.xdefine("runtime.pclntab", sym.SRODATA, int64(pclntab.Vaddr))
-	ctxt.xdefine("runtime.epclntab", sym.SRODATA, int64(pclntab.Vaddr+pclntab.Length))
-	ctxt.xdefine("runtime.noptrdata", sym.SNOPTRDATA, int64(noptr.Vaddr))
-	ctxt.xdefine("runtime.enoptrdata", sym.SNOPTRDATA, int64(noptr.Vaddr+noptr.Length))
-	ctxt.xdefine("runtime.bss", sym.SBSS, int64(bss.Vaddr))
-	ctxt.xdefine("runtime.ebss", sym.SBSS, int64(bss.Vaddr+bss.Length))
-	ctxt.xdefine("runtime.data", sym.SDATA, int64(data.Vaddr))
-	ctxt.xdefine("runtime.edata", sym.SDATA, int64(data.Vaddr+data.Length))
-	ctxt.xdefine("runtime.noptrbss", sym.SNOPTRBSS, int64(noptrbss.Vaddr))
-	ctxt.xdefine("runtime.enoptrbss", sym.SNOPTRBSS, int64(noptrbss.Vaddr+noptrbss.Length))
-	ctxt.xdefine("runtime.end", sym.SBSS, int64(Segdata.Vaddr+Segdata.Length))
-
-	return order
-}
-
-// layout assigns file offsets and lengths to the segments in order.
-// Returns the file size containing all the segments.
-func (ctxt *Link) layout(order []*sym.Segment) uint64 {
-	var prev *sym.Segment
-	for _, seg := range order {
-		if prev == nil {
-			seg.Fileoff = uint64(HEADR)
-		} else {
-			switch ctxt.HeadType {
-			default:
-				// Assuming the previous segment was
-				// aligned, the following rounding
-				// should ensure that this segment's
-				// VA ≡ Fileoff mod FlagRound.
-				seg.Fileoff = uint64(Rnd(int64(prev.Fileoff+prev.Filelen), int64(*FlagRound)))
-				if seg.Vaddr%uint64(*FlagRound) != seg.Fileoff%uint64(*FlagRound) {
-					Exitf("bad segment rounding (Vaddr=%#x Fileoff=%#x FlagRound=%#x)", seg.Vaddr, seg.Fileoff, *FlagRound)
-				}
-			case objabi.Hwindows:
-				seg.Fileoff = prev.Fileoff + uint64(Rnd(int64(prev.Filelen), PEFILEALIGN))
-			case objabi.Hplan9:
-				seg.Fileoff = prev.Fileoff + prev.Filelen
-			}
-		}
-		if seg != &Segdata {
-			// Link.address already set Segdata.Filelen to
-			// account for BSS.
-			seg.Filelen = seg.Length
-		}
-		prev = seg
-	}
-	return prev.Fileoff + prev.Filelen
-}
-
-// add a trampoline with symbol s (to be laid down after the current function)
-func (ctxt *Link) AddTramp(s *sym.Symbol) {
-	s.Type = sym.STEXT
-	s.Attr |= sym.AttrReachable
-	s.Attr |= sym.AttrOnList
-	ctxt.tramps = append(ctxt.tramps, s)
-	if *FlagDebugTramp > 0 && ctxt.Debugvlog > 0 {
-		ctxt.Logf("trampoline %s inserted\n", s)
-	}
-}
-
-// 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 {
-	var total int64
-	for _, sym := range syms {
-		total += sym.Size
-	}
-
-	var buf bytes.Buffer
-	buf.Write([]byte("ZLIB"))
-	var sizeBytes [8]byte
-	binary.BigEndian.PutUint64(sizeBytes[:], uint64(total))
-	buf.Write(sizeBytes[:])
-
-	// Using zlib.BestSpeed achieves very nearly the same
-	// compression levels of zlib.DefaultCompression, but takes
-	// substantially less time. This is important because DWARF
-	// compression can be a significant fraction of link time.
-	z, err := zlib.NewWriterLevel(&buf, zlib.BestSpeed)
-	if err != nil {
-		log.Fatalf("NewWriterLevel failed: %s", err)
-	}
-	for _, s := range syms {
-		// s.P 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 {
-			ctxt.relocbuf = append(ctxt.relocbuf[:0], s.P...)
-			s.P = ctxt.relocbuf
-			s.Attr.Set(sym.AttrReadOnly, false)
-		}
-		relocsym(ctxt, s)
-		if _, err := z.Write(s.P); err != nil {
-			log.Fatalf("compression failed: %s", err)
-		}
-		for i := s.Size - int64(len(s.P)); i > 0; {
-			b := zeros[:]
-			if i < int64(len(b)) {
-				b = b[:i]
-			}
-			n, err := z.Write(b)
-			if err != nil {
-				log.Fatalf("compression failed: %s", err)
-			}
-			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
-			s.Attr.Set(sym.AttrReadOnly, wasReadOnly)
-			for i := range s.R {
-				s.R[i].Done = false
-			}
-		}
-	}
-	if err := z.Close(); err != nil {
-		log.Fatalf("compression failed: %s", err)
-	}
-	if int64(buf.Len()) >= total {
-		// Compression didn't save any space.
-		return nil
-	}
-	return buf.Bytes()
-}
diff --git a/src/cmd/oldlink/internal/ld/deadcode.go b/src/cmd/oldlink/internal/ld/deadcode.go
deleted file mode 100644
index 6a6813a..0000000
--- a/src/cmd/oldlink/internal/ld/deadcode.go
+++ /dev/null
@@ -1,409 +0,0 @@
-// Copyright 2016 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/objabi"
-	"cmd/internal/sys"
-	"cmd/oldlink/internal/sym"
-	"fmt"
-	"strings"
-	"unicode"
-)
-
-// deadcode marks all reachable symbols.
-//
-// The basis of the dead code elimination is a flood fill of symbols,
-// following their relocations, beginning at *flagEntrySymbol.
-//
-// This flood fill is wrapped in logic for pruning unused methods.
-// All methods are mentioned by relocations on their receiver's *rtype.
-// These relocations are specially defined as R_METHODOFF by the compiler
-// so we can detect and manipulated them here.
-//
-// There are three ways a method of a reachable type can be invoked:
-//
-//	1. direct call
-//	2. through a reachable interface type
-//	3. reflect.Value.Method (or MethodByName), or reflect.Type.Method
-//	   (or MethodByName)
-//
-// The first case is handled by the flood fill, a directly called method
-// is marked as reachable.
-//
-// The second case is handled by decomposing all reachable interface
-// types into method signatures. Each encountered method is compared
-// against the interface method signatures, if it matches it is marked
-// as reachable. This is extremely conservative, but easy and correct.
-//
-// The third case is handled by looking to see if any of:
-//	- reflect.Value.Method or MethodByName is reachable
-// 	- reflect.Type.Method or MethodByName is called (through the
-// 	  REFLECTMETHOD attribute marked by the compiler).
-// If any of these happen, all bets are off and all exported methods
-// of reachable types are marked reachable.
-//
-// Any unreached text symbols are removed from ctxt.Textp.
-func deadcode(ctxt *Link) {
-	if ctxt.Debugvlog != 0 {
-		ctxt.Logf("deadcode\n")
-	}
-
-	if *flagNewobj {
-		deadcode2(ctxt)
-		return
-	}
-
-	d := &deadcodepass{
-		ctxt:        ctxt,
-		ifaceMethod: make(map[methodsig]bool),
-	}
-
-	// First, flood fill any symbols directly reachable in the call
-	// graph from *flagEntrySymbol. Ignore all methods not directly called.
-	d.init()
-	d.flood()
-
-	methSym := ctxt.Syms.ROLookup("reflect.Value.Method", sym.SymVerABIInternal)
-	methByNameSym := ctxt.Syms.ROLookup("reflect.Value.MethodByName", sym.SymVerABIInternal)
-	reflectSeen := false
-
-	if ctxt.DynlinkingGo() {
-		// Exported methods may satisfy interfaces we don't know
-		// about yet when dynamically linking.
-		reflectSeen = true
-	}
-
-	for {
-		if !reflectSeen {
-			if d.reflectMethod || (methSym != nil && methSym.Attr.Reachable()) || (methByNameSym != nil && methByNameSym.Attr.Reachable()) {
-				// Methods might be called via reflection. Give up on
-				// static analysis, mark all exported methods of
-				// all reachable types as reachable.
-				reflectSeen = true
-			}
-		}
-
-		// Mark all methods that could satisfy a discovered
-		// interface as reachable. We recheck old marked interfaces
-		// as new types (with new methods) may have been discovered
-		// in the last pass.
-		var rem []methodref
-		for _, m := range d.markableMethods {
-			if (reflectSeen && m.isExported()) || d.ifaceMethod[m.m] {
-				d.markMethod(m)
-			} else {
-				rem = append(rem, m)
-			}
-		}
-		d.markableMethods = rem
-
-		if len(d.markQueue) == 0 {
-			// No new work was discovered. Done.
-			break
-		}
-		d.flood()
-	}
-
-	// Remove all remaining unreached R_METHODOFF relocations.
-	for _, m := range d.markableMethods {
-		for _, r := range m.r {
-			d.cleanupReloc(r)
-		}
-	}
-
-	if ctxt.BuildMode != BuildModeShared {
-		// Keep a itablink if the symbol it points at is being kept.
-		// (When BuildModeShared, always keep itablinks.)
-		for _, s := range ctxt.Syms.Allsym {
-			if strings.HasPrefix(s.Name, "go.itablink.") {
-				s.Attr.Set(sym.AttrReachable, len(s.R) == 1 && s.R[0].Sym.Attr.Reachable())
-			}
-		}
-	}
-
-	addToTextp(ctxt)
-}
-
-func addToTextp(ctxt *Link) {
-	// Remove dead text but keep file information (z symbols).
-	textp := []*sym.Symbol{}
-	for _, s := range ctxt.Textp {
-		if s.Attr.Reachable() {
-			textp = append(textp, s)
-		}
-	}
-
-	// Put reachable text symbols into Textp.
-	// do it in postorder so that packages are laid down in dependency order
-	// internal first, then everything else
-	ctxt.Library = postorder(ctxt.Library)
-	for _, doInternal := range [2]bool{true, false} {
-		for _, lib := range ctxt.Library {
-			if isRuntimeDepPkg(lib.Pkg) != doInternal {
-				continue
-			}
-			libtextp := lib.Textp[:0]
-			for _, s := range lib.Textp {
-				if s.Attr.Reachable() {
-					textp = append(textp, s)
-					libtextp = append(libtextp, s)
-					if s.Unit != nil {
-						s.Unit.Textp = append(s.Unit.Textp, s)
-					}
-				}
-			}
-			for _, s := range lib.DupTextSyms {
-				if s.Attr.Reachable() && !s.Attr.OnList() {
-					textp = append(textp, s)
-					libtextp = append(libtextp, s)
-					if s.Unit != nil {
-						s.Unit.Textp = append(s.Unit.Textp, s)
-					}
-					s.Attr |= sym.AttrOnList
-					// dupok symbols may be defined in multiple packages. its
-					// associated package is chosen sort of arbitrarily (the
-					// first containing package that the linker loads). canonicalize
-					// it here to the package with which it will be laid down
-					// in text.
-					s.File = objabi.PathToPrefix(lib.Pkg)
-				}
-			}
-			lib.Textp = libtextp
-		}
-	}
-	ctxt.Textp = textp
-
-	if len(ctxt.Shlibs) > 0 {
-		// We might have overwritten some functions above (this tends to happen for the
-		// autogenerated type equality/hashing functions) and we don't want to generated
-		// pcln table entries for these any more so remove them from Textp.
-		textp := make([]*sym.Symbol, 0, len(ctxt.Textp))
-		for _, s := range ctxt.Textp {
-			if s.Type != sym.SDYNIMPORT {
-				textp = append(textp, s)
-			}
-		}
-		ctxt.Textp = textp
-	}
-}
-
-// methodref holds the relocations from a receiver type symbol to its
-// method. There are three relocations, one for each of the fields in
-// the reflect.method struct: mtyp, ifn, and tfn.
-type methodref struct {
-	m   methodsig
-	src *sym.Symbol   // receiver type symbol
-	r   [3]*sym.Reloc // R_METHODOFF relocations to fields of runtime.method
-}
-
-func (m methodref) ifn() *sym.Symbol { return m.r[1].Sym }
-
-func (m methodref) isExported() bool {
-	for _, r := range m.m {
-		return unicode.IsUpper(r)
-	}
-	panic("methodref has no signature")
-}
-
-// deadcodepass holds state for the deadcode flood fill.
-type deadcodepass struct {
-	ctxt            *Link
-	markQueue       []*sym.Symbol      // symbols to flood fill in next pass
-	ifaceMethod     map[methodsig]bool // methods declared in reached interfaces
-	markableMethods []methodref        // methods of reached types
-	reflectMethod   bool
-}
-
-func (d *deadcodepass) cleanupReloc(r *sym.Reloc) {
-	if r.Sym.Attr.Reachable() {
-		r.Type = objabi.R_ADDROFF
-	} else {
-		if d.ctxt.Debugvlog > 1 {
-			d.ctxt.Logf("removing method %s\n", r.Sym.Name)
-		}
-		r.Sym = nil
-		r.Siz = 0
-	}
-}
-
-// mark appends a symbol to the mark queue for flood filling.
-func (d *deadcodepass) mark(s, parent *sym.Symbol) {
-	if s == nil || s.Attr.Reachable() {
-		return
-	}
-	if s.Attr.ReflectMethod() {
-		d.reflectMethod = true
-	}
-	if *flagDumpDep {
-		p := "_"
-		if parent != nil {
-			p = parent.Name
-		}
-		fmt.Printf("%s -> %s\n", p, s.Name)
-	}
-	s.Attr |= sym.AttrReachable
-	if d.ctxt.Reachparent != nil {
-		d.ctxt.Reachparent[s] = parent
-	}
-	d.markQueue = append(d.markQueue, s)
-}
-
-// markMethod marks a method as reachable.
-func (d *deadcodepass) markMethod(m methodref) {
-	for _, r := range m.r {
-		d.mark(r.Sym, m.src)
-		r.Type = objabi.R_ADDROFF
-	}
-}
-
-// init marks all initial symbols as reachable.
-// In a typical binary, this is *flagEntrySymbol.
-func (d *deadcodepass) init() {
-	var names []string
-
-	if d.ctxt.BuildMode == BuildModeShared {
-		// Mark all symbols defined in this library as reachable when
-		// building a shared library.
-		for _, s := range d.ctxt.Syms.Allsym {
-			if s.Type != 0 && s.Type != sym.SDYNIMPORT {
-				d.mark(s, nil)
-			}
-		}
-	} else {
-		// In a normal binary, start at main.main and the init
-		// functions and mark what is reachable from there.
-
-		if d.ctxt.linkShared && (d.ctxt.BuildMode == BuildModeExe || d.ctxt.BuildMode == BuildModePIE) {
-			names = append(names, "main.main", "main..inittask")
-		} else {
-			// The external linker refers main symbol directly.
-			if d.ctxt.LinkMode == LinkExternal && (d.ctxt.BuildMode == BuildModeExe || d.ctxt.BuildMode == BuildModePIE) {
-				if d.ctxt.HeadType == objabi.Hwindows && d.ctxt.Arch.Family == sys.I386 {
-					*flagEntrySymbol = "_main"
-				} else {
-					*flagEntrySymbol = "main"
-				}
-			}
-			names = append(names, *flagEntrySymbol)
-			if d.ctxt.BuildMode == BuildModePlugin {
-				names = append(names, objabi.PathToPrefix(*flagPluginPath)+"..inittask", objabi.PathToPrefix(*flagPluginPath)+".main", "go.plugin.tabs")
-
-				// We don't keep the go.plugin.exports symbol,
-				// but we do keep the symbols it refers to.
-				exports := d.ctxt.Syms.ROLookup("go.plugin.exports", 0)
-				if exports != nil {
-					for i := range exports.R {
-						d.mark(exports.R[i].Sym, nil)
-					}
-				}
-			}
-		}
-		for _, s := range dynexp {
-			d.mark(s, nil)
-		}
-	}
-
-	for _, name := range names {
-		// Mark symbol as a data/ABI0 symbol.
-		d.mark(d.ctxt.Syms.ROLookup(name, 0), nil)
-		// Also mark any Go functions (internal ABI).
-		d.mark(d.ctxt.Syms.ROLookup(name, sym.SymVerABIInternal), nil)
-	}
-}
-
-// flood fills symbols reachable from the markQueue symbols.
-// As it goes, it collects methodref and interface method declarations.
-func (d *deadcodepass) flood() {
-	for len(d.markQueue) > 0 {
-		s := d.markQueue[0]
-		d.markQueue = d.markQueue[1:]
-		if s.Type == sym.STEXT {
-			if d.ctxt.Debugvlog > 1 {
-				d.ctxt.Logf("marktext %s\n", s.Name)
-			}
-		}
-
-		if strings.HasPrefix(s.Name, "type.") && s.Name[5] != '.' {
-			if len(s.P) == 0 {
-				// Probably a bug. The undefined symbol check
-				// later will give a better error than deadcode.
-				continue
-			}
-			if decodetypeKind(d.ctxt.Arch, s.P)&kindMask == kindInterface {
-				for _, sig := range decodeIfaceMethods(d.ctxt.Arch, s) {
-					if d.ctxt.Debugvlog > 1 {
-						d.ctxt.Logf("reached iface method: %s\n", sig)
-					}
-					d.ifaceMethod[sig] = true
-				}
-			}
-		}
-
-		mpos := 0 // 0-3, the R_METHODOFF relocs of runtime.uncommontype
-		var methods []methodref
-		for i := range s.R {
-			r := &s.R[i]
-			if r.Sym == nil {
-				continue
-			}
-			if r.Type == objabi.R_WEAKADDROFF {
-				// An R_WEAKADDROFF relocation is not reason
-				// enough to mark the pointed-to symbol as
-				// reachable.
-				continue
-			}
-			if r.Sym.Type == sym.SABIALIAS {
-				// Patch this relocation through the
-				// ABI alias before marking.
-				r.Sym = resolveABIAlias(r.Sym)
-			}
-			if r.Type != objabi.R_METHODOFF {
-				d.mark(r.Sym, s)
-				continue
-			}
-			// Collect rtype pointers to methods for
-			// later processing in deadcode.
-			if mpos == 0 {
-				m := methodref{src: s}
-				m.r[0] = r
-				methods = append(methods, m)
-			} else {
-				methods[len(methods)-1].r[mpos] = r
-			}
-			mpos++
-			if mpos == len(methodref{}.r) {
-				mpos = 0
-			}
-		}
-		if len(methods) > 0 {
-			// Decode runtime type information for type methods
-			// to help work out which methods can be called
-			// dynamically via interfaces.
-			methodsigs := decodetypeMethods(d.ctxt.Arch, s)
-			if len(methods) != len(methodsigs) {
-				panic(fmt.Sprintf("%q has %d method relocations for %d methods", s.Name, len(methods), len(methodsigs)))
-			}
-			for i, m := range methodsigs {
-				name := string(m)
-				name = name[:strings.Index(name, "(")]
-				if !strings.HasSuffix(methods[i].ifn().Name, name) {
-					panic(fmt.Sprintf("%q relocation for %q does not match method %q", s.Name, methods[i].ifn().Name, name))
-				}
-				methods[i].m = m
-			}
-			d.markableMethods = append(d.markableMethods, methods...)
-		}
-
-		if s.FuncInfo != nil {
-			for i := range s.FuncInfo.Funcdata {
-				d.mark(s.FuncInfo.Funcdata[i], s)
-			}
-		}
-		d.mark(s.Gotype, s)
-		d.mark(s.Sub, s)
-		d.mark(s.Outer, s)
-	}
-}
diff --git a/src/cmd/oldlink/internal/ld/deadcode2.go b/src/cmd/oldlink/internal/ld/deadcode2.go
deleted file mode 100644
index 82bfd60..0000000
--- a/src/cmd/oldlink/internal/ld/deadcode2.go
+++ /dev/null
@@ -1,441 +0,0 @@
-// Copyright 2019 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 (
-	"bytes"
-	"cmd/internal/dwarf"
-	"cmd/internal/objabi"
-	"cmd/internal/sys"
-	"cmd/oldlink/internal/loader"
-	"cmd/oldlink/internal/sym"
-	"container/heap"
-	"fmt"
-	"unicode"
-)
-
-var _ = fmt.Print
-
-type workQueue []loader.Sym
-
-// Implement container/heap.Interface.
-func (q *workQueue) Len() int           { return len(*q) }
-func (q *workQueue) Less(i, j int) bool { return (*q)[i] < (*q)[j] }
-func (q *workQueue) Swap(i, j int)      { (*q)[i], (*q)[j] = (*q)[j], (*q)[i] }
-func (q *workQueue) Push(i interface{}) { *q = append(*q, i.(loader.Sym)) }
-func (q *workQueue) Pop() interface{}   { i := (*q)[len(*q)-1]; *q = (*q)[:len(*q)-1]; return i }
-
-// Functions for deadcode pass to use.
-// Deadcode pass should call push/pop, not Push/Pop.
-func (q *workQueue) push(i loader.Sym) { heap.Push(q, i) }
-func (q *workQueue) pop() loader.Sym   { return heap.Pop(q).(loader.Sym) }
-func (q *workQueue) empty() bool       { return len(*q) == 0 }
-
-type deadcodePass2 struct {
-	ctxt *Link
-	ldr  *loader.Loader
-	wq   workQueue
-	rtmp []loader.Reloc
-
-	ifaceMethod     map[methodsig]bool // methods declared in reached interfaces
-	markableMethods []methodref2       // methods of reached types
-	reflectSeen     bool               // whether we have seen a reflect method call
-}
-
-func (d *deadcodePass2) init() {
-	d.ldr.InitReachable()
-	d.ifaceMethod = make(map[methodsig]bool)
-	if d.ctxt.Reachparent != nil {
-		d.ldr.Reachparent = make([]loader.Sym, d.ldr.NSym())
-	}
-	heap.Init(&d.wq)
-
-	if d.ctxt.BuildMode == BuildModeShared {
-		// Mark all symbols defined in this library as reachable when
-		// building a shared library.
-		n := d.ldr.NDef()
-		for i := 1; i < n; i++ {
-			s := loader.Sym(i)
-			if !d.ldr.IsDup(s) {
-				d.mark(s, 0)
-			}
-		}
-		return
-	}
-
-	var names []string
-
-	// In a normal binary, start at main.main and the init
-	// functions and mark what is reachable from there.
-	if d.ctxt.linkShared && (d.ctxt.BuildMode == BuildModeExe || d.ctxt.BuildMode == BuildModePIE) {
-		names = append(names, "main.main", "main..inittask")
-	} else {
-		// The external linker refers main symbol directly.
-		if d.ctxt.LinkMode == LinkExternal && (d.ctxt.BuildMode == BuildModeExe || d.ctxt.BuildMode == BuildModePIE) {
-			if d.ctxt.HeadType == objabi.Hwindows && d.ctxt.Arch.Family == sys.I386 {
-				*flagEntrySymbol = "_main"
-			} else {
-				*flagEntrySymbol = "main"
-			}
-		}
-		names = append(names, *flagEntrySymbol)
-		if d.ctxt.BuildMode == BuildModePlugin {
-			names = append(names, objabi.PathToPrefix(*flagPluginPath)+"..inittask", objabi.PathToPrefix(*flagPluginPath)+".main", "go.plugin.tabs")
-
-			// We don't keep the go.plugin.exports symbol,
-			// but we do keep the symbols it refers to.
-			exportsIdx := d.ldr.Lookup("go.plugin.exports", 0)
-			if exportsIdx != 0 {
-				d.ReadRelocs(exportsIdx)
-				for i := 0; i < len(d.rtmp); i++ {
-					d.mark(d.rtmp[i].Sym, 0)
-				}
-			}
-		}
-	}
-
-	dynexpMap := d.ctxt.cgo_export_dynamic
-	if d.ctxt.LinkMode == LinkExternal {
-		dynexpMap = d.ctxt.cgo_export_static
-	}
-	for exp := range dynexpMap {
-		names = append(names, exp)
-	}
-
-	// DWARF constant DIE symbols are not referenced, but needed by
-	// the dwarf pass.
-	if !*FlagW {
-		for _, lib := range d.ctxt.Library {
-			names = append(names, dwarf.ConstInfoPrefix+lib.Pkg)
-		}
-	}
-
-	for _, name := range names {
-		// Mark symbol as a data/ABI0 symbol.
-		d.mark(d.ldr.Lookup(name, 0), 0)
-		// Also mark any Go functions (internal ABI).
-		d.mark(d.ldr.Lookup(name, sym.SymVerABIInternal), 0)
-	}
-}
-
-func (d *deadcodePass2) flood() {
-	symRelocs := []loader.Reloc{}
-	auxSyms := []loader.Sym{}
-	for !d.wq.empty() {
-		symIdx := d.wq.pop()
-
-		d.reflectSeen = d.reflectSeen || d.ldr.IsReflectMethod(symIdx)
-
-		relocs := d.ldr.Relocs(symIdx)
-		symRelocs = relocs.ReadAll(symRelocs)
-
-		if d.ldr.IsGoType(symIdx) {
-			p := d.ldr.Data(symIdx)
-			if len(p) != 0 && decodetypeKind(d.ctxt.Arch, p)&kindMask == kindInterface {
-				for _, sig := range d.decodeIfaceMethods2(d.ldr, d.ctxt.Arch, symIdx, symRelocs) {
-					if d.ctxt.Debugvlog > 1 {
-						d.ctxt.Logf("reached iface method: %s\n", sig)
-					}
-					d.ifaceMethod[sig] = true
-				}
-			}
-		}
-
-		var methods []methodref2
-		for i := 0; i < relocs.Count; i++ {
-			r := symRelocs[i]
-			if r.Type == objabi.R_WEAKADDROFF {
-				continue
-			}
-			if r.Type == objabi.R_METHODOFF {
-				if i+2 >= relocs.Count {
-					panic("expect three consecutive R_METHODOFF relocs")
-				}
-				methods = append(methods, methodref2{src: symIdx, r: i})
-				i += 2
-				continue
-			}
-			if r.Type == objabi.R_USETYPE {
-				// type symbol used for DWARF. we need to load the symbol but it may not
-				// be otherwise reachable in the program.
-				// do nothing for now as we still load all type symbols.
-				continue
-			}
-			d.mark(r.Sym, symIdx)
-		}
-		auxSyms = d.ldr.ReadAuxSyms(symIdx, auxSyms)
-		for i := 0; i < len(auxSyms); i++ {
-			d.mark(auxSyms[i], symIdx)
-		}
-		// Some host object symbols have an outer object, which acts like a
-		// "carrier" symbol, or it holds all the symbols for a particular
-		// section. We need to mark all "referenced" symbols from that carrier,
-		// so we make sure we're pulling in all outer symbols, and their sub
-		// symbols. This is not ideal, and these carrier/section symbols could
-		// be removed.
-		d.mark(d.ldr.OuterSym(symIdx), symIdx)
-		d.mark(d.ldr.SubSym(symIdx), symIdx)
-
-		if len(methods) != 0 {
-			// Decode runtime type information for type methods
-			// to help work out which methods can be called
-			// dynamically via interfaces.
-			methodsigs := d.decodetypeMethods2(d.ldr, d.ctxt.Arch, symIdx, symRelocs)
-			if len(methods) != len(methodsigs) {
-				panic(fmt.Sprintf("%q has %d method relocations for %d methods", d.ldr.SymName(symIdx), len(methods), len(methodsigs)))
-			}
-			for i, m := range methodsigs {
-				methods[i].m = m
-			}
-			d.markableMethods = append(d.markableMethods, methods...)
-		}
-	}
-}
-
-func (d *deadcodePass2) mark(symIdx, parent loader.Sym) {
-	if symIdx != 0 && !d.ldr.Reachable.Has(symIdx) {
-		d.wq.push(symIdx)
-		d.ldr.Reachable.Set(symIdx)
-		if d.ctxt.Reachparent != nil {
-			d.ldr.Reachparent[symIdx] = parent
-		}
-		if *flagDumpDep {
-			to := d.ldr.SymName(symIdx)
-			if to != "" {
-				from := "_"
-				if parent != 0 {
-					from = d.ldr.SymName(parent)
-				}
-				fmt.Printf("%s -> %s\n", from, to)
-			}
-		}
-	}
-}
-
-func (d *deadcodePass2) markMethod(m methodref2) {
-	d.ReadRelocs(m.src)
-	d.mark(d.rtmp[m.r].Sym, m.src)
-	d.mark(d.rtmp[m.r+1].Sym, m.src)
-	d.mark(d.rtmp[m.r+2].Sym, m.src)
-}
-
-func deadcode2(ctxt *Link) {
-	ldr := ctxt.loader
-	d := deadcodePass2{ctxt: ctxt, ldr: ldr}
-	d.init()
-	d.flood()
-
-	callSym := ldr.Lookup("reflect.Value.Call", sym.SymVerABIInternal)
-	methSym := ldr.Lookup("reflect.Value.Method", sym.SymVerABIInternal)
-	if ctxt.DynlinkingGo() {
-		// Exported methods may satisfy interfaces we don't know
-		// about yet when dynamically linking.
-		d.reflectSeen = true
-	}
-
-	for {
-		// Methods might be called via reflection. Give up on
-		// static analysis, mark all exported methods of
-		// all reachable types as reachable.
-		d.reflectSeen = d.reflectSeen || (callSym != 0 && ldr.Reachable.Has(callSym)) || (methSym != 0 && ldr.Reachable.Has(methSym))
-
-		// Mark all methods that could satisfy a discovered
-		// interface as reachable. We recheck old marked interfaces
-		// as new types (with new methods) may have been discovered
-		// in the last pass.
-		rem := d.markableMethods[:0]
-		for _, m := range d.markableMethods {
-			if (d.reflectSeen && m.isExported()) || d.ifaceMethod[m.m] {
-				d.markMethod(m)
-			} else {
-				rem = append(rem, m)
-			}
-		}
-		d.markableMethods = rem
-
-		if d.wq.empty() {
-			// No new work was discovered. Done.
-			break
-		}
-		d.flood()
-	}
-
-	n := ldr.NSym()
-
-	if ctxt.BuildMode != BuildModeShared {
-		// Keep a itablink if the symbol it points at is being kept.
-		// (When BuildModeShared, always keep itablinks.)
-		for i := 1; i < n; i++ {
-			s := loader.Sym(i)
-			if ldr.IsItabLink(s) {
-				relocs := ldr.Relocs(s)
-				if relocs.Count > 0 && ldr.Reachable.Has(relocs.At(0).Sym) {
-					ldr.Reachable.Set(s)
-				}
-			}
-		}
-	}
-}
-
-// methodref2 holds the relocations from a receiver type symbol to its
-// method. There are three relocations, one for each of the fields in
-// the reflect.method struct: mtyp, ifn, and tfn.
-type methodref2 struct {
-	m   methodsig
-	src loader.Sym // receiver type symbol
-	r   int        // the index of R_METHODOFF relocations
-}
-
-func (m methodref2) isExported() bool {
-	for _, r := range m.m {
-		return unicode.IsUpper(r)
-	}
-	panic("methodref has no signature")
-}
-
-// decodeMethodSig2 decodes an array of method signature information.
-// Each element of the array is size bytes. The first 4 bytes is a
-// nameOff for the method name, and the next 4 bytes is a typeOff for
-// the function type.
-//
-// Conveniently this is the layout of both runtime.method and runtime.imethod.
-func (d *deadcodePass2) decodeMethodSig2(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym, symRelocs []loader.Reloc, off, size, count int) []methodsig {
-	var buf bytes.Buffer
-	var methods []methodsig
-	for i := 0; i < count; i++ {
-		buf.WriteString(decodetypeName2(ldr, symIdx, symRelocs, off))
-		mtypSym := decodeRelocSym2(ldr, symIdx, symRelocs, int32(off+4))
-		// FIXME: add some sort of caching here, since we may see some of the
-		// same symbols over time for param types.
-		d.ReadRelocs(mtypSym)
-		mp := ldr.Data(mtypSym)
-
-		buf.WriteRune('(')
-		inCount := decodetypeFuncInCount(arch, mp)
-		for i := 0; i < inCount; i++ {
-			if i > 0 {
-				buf.WriteString(", ")
-			}
-			a := d.decodetypeFuncInType2(ldr, arch, mtypSym, d.rtmp, i)
-			buf.WriteString(ldr.SymName(a))
-		}
-		buf.WriteString(") (")
-		outCount := decodetypeFuncOutCount(arch, mp)
-		for i := 0; i < outCount; i++ {
-			if i > 0 {
-				buf.WriteString(", ")
-			}
-			a := d.decodetypeFuncOutType2(ldr, arch, mtypSym, d.rtmp, i)
-			buf.WriteString(ldr.SymName(a))
-		}
-		buf.WriteRune(')')
-
-		off += size
-		methods = append(methods, methodsig(buf.String()))
-		buf.Reset()
-	}
-	return methods
-}
-
-func (d *deadcodePass2) decodeIfaceMethods2(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym, symRelocs []loader.Reloc) []methodsig {
-	p := ldr.Data(symIdx)
-	if decodetypeKind(arch, p)&kindMask != kindInterface {
-		panic(fmt.Sprintf("symbol %q is not an interface", ldr.SymName(symIdx)))
-	}
-	rel := decodeReloc2(ldr, symIdx, symRelocs, int32(commonsize(arch)+arch.PtrSize))
-	if rel.Sym == 0 {
-		return nil
-	}
-	if rel.Sym != symIdx {
-		panic(fmt.Sprintf("imethod slice pointer in %q leads to a different symbol", ldr.SymName(symIdx)))
-	}
-	off := int(rel.Add) // array of reflect.imethod values
-	numMethods := int(decodetypeIfaceMethodCount(arch, p))
-	sizeofIMethod := 4 + 4
-	return d.decodeMethodSig2(ldr, arch, symIdx, symRelocs, off, sizeofIMethod, numMethods)
-}
-
-func (d *deadcodePass2) decodetypeMethods2(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym, symRelocs []loader.Reloc) []methodsig {
-	p := ldr.Data(symIdx)
-	if !decodetypeHasUncommon(arch, p) {
-		panic(fmt.Sprintf("no methods on %q", ldr.SymName(symIdx)))
-	}
-	off := commonsize(arch) // reflect.rtype
-	switch decodetypeKind(arch, p) & kindMask {
-	case kindStruct: // reflect.structType
-		off += 4 * arch.PtrSize
-	case kindPtr: // reflect.ptrType
-		off += arch.PtrSize
-	case kindFunc: // reflect.funcType
-		off += arch.PtrSize // 4 bytes, pointer aligned
-	case kindSlice: // reflect.sliceType
-		off += arch.PtrSize
-	case kindArray: // reflect.arrayType
-		off += 3 * arch.PtrSize
-	case kindChan: // reflect.chanType
-		off += 2 * arch.PtrSize
-	case kindMap: // reflect.mapType
-		off += 4*arch.PtrSize + 8
-	case kindInterface: // reflect.interfaceType
-		off += 3 * arch.PtrSize
-	default:
-		// just Sizeof(rtype)
-	}
-
-	mcount := int(decodeInuxi(arch, p[off+4:], 2))
-	moff := int(decodeInuxi(arch, p[off+4+2+2:], 4))
-	off += moff                // offset to array of reflect.method values
-	const sizeofMethod = 4 * 4 // sizeof reflect.method in program
-	return d.decodeMethodSig2(ldr, arch, symIdx, symRelocs, off, sizeofMethod, mcount)
-}
-
-func decodeReloc2(ldr *loader.Loader, symIdx loader.Sym, symRelocs []loader.Reloc, off int32) loader.Reloc {
-	for j := 0; j < len(symRelocs); j++ {
-		rel := symRelocs[j]
-		if rel.Off == off {
-			return rel
-		}
-	}
-	return loader.Reloc{}
-}
-
-func decodeRelocSym2(ldr *loader.Loader, symIdx loader.Sym, symRelocs []loader.Reloc, off int32) loader.Sym {
-	return decodeReloc2(ldr, symIdx, symRelocs, off).Sym
-}
-
-// decodetypeName2 decodes the name from a reflect.name.
-func decodetypeName2(ldr *loader.Loader, symIdx loader.Sym, symRelocs []loader.Reloc, off int) string {
-	r := decodeRelocSym2(ldr, symIdx, symRelocs, int32(off))
-	if r == 0 {
-		return ""
-	}
-
-	data := ldr.Data(r)
-	namelen := int(uint16(data[1])<<8 | uint16(data[2]))
-	return string(data[3 : 3+namelen])
-}
-
-func (d *deadcodePass2) decodetypeFuncInType2(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym, symRelocs []loader.Reloc, i int) loader.Sym {
-	uadd := commonsize(arch) + 4
-	if arch.PtrSize == 8 {
-		uadd += 4
-	}
-	if decodetypeHasUncommon(arch, ldr.Data(symIdx)) {
-		uadd += uncommonSize()
-	}
-	return decodeRelocSym2(ldr, symIdx, symRelocs, int32(uadd+i*arch.PtrSize))
-}
-
-func (d *deadcodePass2) decodetypeFuncOutType2(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym, symRelocs []loader.Reloc, i int) loader.Sym {
-	return d.decodetypeFuncInType2(ldr, arch, symIdx, symRelocs, i+decodetypeFuncInCount(arch, ldr.Data(symIdx)))
-}
-
-// readRelocs reads the relocations for the specified symbol into the
-// deadcode relocs work array. Use with care, since the work array
-// is a singleton.
-func (d *deadcodePass2) ReadRelocs(symIdx loader.Sym) {
-	relocs := d.ldr.Relocs(symIdx)
-	d.rtmp = relocs.ReadAll(d.rtmp)
-}
diff --git a/src/cmd/oldlink/internal/ld/decodesym.go b/src/cmd/oldlink/internal/ld/decodesym.go
deleted file mode 100644
index 0676e94..0000000
--- a/src/cmd/oldlink/internal/ld/decodesym.go
+++ /dev/null
@@ -1,374 +0,0 @@
-// Copyright 2012 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 (
-	"bytes"
-	"cmd/internal/objabi"
-	"cmd/internal/sys"
-	"cmd/oldlink/internal/sym"
-	"debug/elf"
-	"fmt"
-)
-
-// Decoding the type.* symbols.	 This has to be in sync with
-// ../../runtime/type.go, or more specifically, with what
-// cmd/compile/internal/gc/reflect.go stuffs in these.
-
-// tflag is documented in reflect/type.go.
-//
-// tflag values must be kept in sync with copies in:
-//	cmd/compile/internal/gc/reflect.go
-//	cmd/oldlink/internal/ld/decodesym.go
-//	reflect/type.go
-//	runtime/type.go
-const (
-	tflagUncommon  = 1 << 0
-	tflagExtraStar = 1 << 1
-)
-
-func decodeReloc(s *sym.Symbol, off int32) *sym.Reloc {
-	for i := range s.R {
-		if s.R[i].Off == off {
-			return &s.R[i]
-		}
-	}
-	return nil
-}
-
-func decodeRelocSym(s *sym.Symbol, off int32) *sym.Symbol {
-	r := decodeReloc(s, off)
-	if r == nil {
-		return nil
-	}
-	return r.Sym
-}
-
-func decodeInuxi(arch *sys.Arch, p []byte, sz int) uint64 {
-	switch sz {
-	case 2:
-		return uint64(arch.ByteOrder.Uint16(p))
-	case 4:
-		return uint64(arch.ByteOrder.Uint32(p))
-	case 8:
-		return arch.ByteOrder.Uint64(p)
-	default:
-		Exitf("dwarf: decode inuxi %d", sz)
-		panic("unreachable")
-	}
-}
-
-func commonsize(arch *sys.Arch) int      { return 4*arch.PtrSize + 8 + 8 } // runtime._type
-func structfieldSize(arch *sys.Arch) int { return 3 * arch.PtrSize }       // runtime.structfield
-func uncommonSize() int                  { return 4 + 2 + 2 + 4 + 4 }      // runtime.uncommontype
-
-// Type.commonType.kind
-func decodetypeKind(arch *sys.Arch, p []byte) uint8 {
-	return p[2*arch.PtrSize+7] & objabi.KindMask //  0x13 / 0x1f
-}
-
-// Type.commonType.kind
-func decodetypeUsegcprog(arch *sys.Arch, p []byte) uint8 {
-	return p[2*arch.PtrSize+7] & objabi.KindGCProg //  0x13 / 0x1f
-}
-
-// Type.commonType.size
-func decodetypeSize(arch *sys.Arch, p []byte) int64 {
-	return int64(decodeInuxi(arch, p, arch.PtrSize)) // 0x8 / 0x10
-}
-
-// Type.commonType.ptrdata
-func decodetypePtrdata(arch *sys.Arch, p []byte) int64 {
-	return int64(decodeInuxi(arch, p[arch.PtrSize:], arch.PtrSize)) // 0x8 / 0x10
-}
-
-// Type.commonType.tflag
-func decodetypeHasUncommon(arch *sys.Arch, p []byte) bool {
-	return p[2*arch.PtrSize+4]&tflagUncommon != 0
-}
-
-// Find the elf.Section of a given shared library that contains a given address.
-func findShlibSection(ctxt *Link, path string, addr uint64) *elf.Section {
-	for _, shlib := range ctxt.Shlibs {
-		if shlib.Path == path {
-			for _, sect := range shlib.File.Sections {
-				if sect.Addr <= addr && addr <= sect.Addr+sect.Size {
-					return sect
-				}
-			}
-		}
-	}
-	return nil
-}
-
-// Type.commonType.gc
-func decodetypeGcprog(ctxt *Link, s *sym.Symbol) []byte {
-	if s.Type == sym.SDYNIMPORT {
-		addr := decodetypeGcprogShlib(ctxt, s)
-		sect := findShlibSection(ctxt, s.File, addr)
-		if sect != nil {
-			// A gcprog is a 4-byte uint32 indicating length, followed by
-			// the actual program.
-			progsize := make([]byte, 4)
-			sect.ReadAt(progsize, int64(addr-sect.Addr))
-			progbytes := make([]byte, ctxt.Arch.ByteOrder.Uint32(progsize))
-			sect.ReadAt(progbytes, int64(addr-sect.Addr+4))
-			return append(progsize, progbytes...)
-		}
-		Exitf("cannot find gcprog for %s", s.Name)
-		return nil
-	}
-	return decodeRelocSym(s, 2*int32(ctxt.Arch.PtrSize)+8+1*int32(ctxt.Arch.PtrSize)).P
-}
-
-func decodetypeGcprogShlib(ctxt *Link, s *sym.Symbol) uint64 {
-	if ctxt.Arch.Family == sys.ARM64 {
-		for _, shlib := range ctxt.Shlibs {
-			if shlib.Path == s.File {
-				return shlib.gcdataAddresses[s]
-			}
-		}
-		return 0
-	}
-	return decodeInuxi(ctxt.Arch, s.P[2*int32(ctxt.Arch.PtrSize)+8+1*int32(ctxt.Arch.PtrSize):], ctxt.Arch.PtrSize)
-}
-
-func decodetypeGcmask(ctxt *Link, s *sym.Symbol) []byte {
-	if s.Type == sym.SDYNIMPORT {
-		addr := decodetypeGcprogShlib(ctxt, s)
-		ptrdata := decodetypePtrdata(ctxt.Arch, s.P)
-		sect := findShlibSection(ctxt, s.File, addr)
-		if sect != nil {
-			r := make([]byte, ptrdata/int64(ctxt.Arch.PtrSize))
-			sect.ReadAt(r, int64(addr-sect.Addr))
-			return r
-		}
-		Exitf("cannot find gcmask for %s", s.Name)
-		return nil
-	}
-	mask := decodeRelocSym(s, 2*int32(ctxt.Arch.PtrSize)+8+1*int32(ctxt.Arch.PtrSize))
-	return mask.P
-}
-
-// Type.ArrayType.elem and Type.SliceType.Elem
-func decodetypeArrayElem(arch *sys.Arch, s *sym.Symbol) *sym.Symbol {
-	return decodeRelocSym(s, int32(commonsize(arch))) // 0x1c / 0x30
-}
-
-func decodetypeArrayLen(arch *sys.Arch, s *sym.Symbol) int64 {
-	return int64(decodeInuxi(arch, s.P[commonsize(arch)+2*arch.PtrSize:], arch.PtrSize))
-}
-
-// Type.PtrType.elem
-func decodetypePtrElem(arch *sys.Arch, s *sym.Symbol) *sym.Symbol {
-	return decodeRelocSym(s, int32(commonsize(arch))) // 0x1c / 0x30
-}
-
-// Type.MapType.key, elem
-func decodetypeMapKey(arch *sys.Arch, s *sym.Symbol) *sym.Symbol {
-	return decodeRelocSym(s, int32(commonsize(arch))) // 0x1c / 0x30
-}
-
-func decodetypeMapValue(arch *sys.Arch, s *sym.Symbol) *sym.Symbol {
-	return decodeRelocSym(s, int32(commonsize(arch))+int32(arch.PtrSize)) // 0x20 / 0x38
-}
-
-// Type.ChanType.elem
-func decodetypeChanElem(arch *sys.Arch, s *sym.Symbol) *sym.Symbol {
-	return decodeRelocSym(s, int32(commonsize(arch))) // 0x1c / 0x30
-}
-
-// Type.FuncType.dotdotdot
-func decodetypeFuncDotdotdot(arch *sys.Arch, p []byte) bool {
-	return uint16(decodeInuxi(arch, p[commonsize(arch)+2:], 2))&(1<<15) != 0
-}
-
-// Type.FuncType.inCount
-func decodetypeFuncInCount(arch *sys.Arch, p []byte) int {
-	return int(decodeInuxi(arch, p[commonsize(arch):], 2))
-}
-
-func decodetypeFuncOutCount(arch *sys.Arch, p []byte) int {
-	return int(uint16(decodeInuxi(arch, p[commonsize(arch)+2:], 2)) & (1<<15 - 1))
-}
-
-func decodetypeFuncInType(arch *sys.Arch, s *sym.Symbol, i int) *sym.Symbol {
-	uadd := commonsize(arch) + 4
-	if arch.PtrSize == 8 {
-		uadd += 4
-	}
-	if decodetypeHasUncommon(arch, s.P) {
-		uadd += uncommonSize()
-	}
-	return decodeRelocSym(s, int32(uadd+i*arch.PtrSize))
-}
-
-func decodetypeFuncOutType(arch *sys.Arch, s *sym.Symbol, i int) *sym.Symbol {
-	return decodetypeFuncInType(arch, s, i+decodetypeFuncInCount(arch, s.P))
-}
-
-// Type.StructType.fields.Slice::length
-func decodetypeStructFieldCount(arch *sys.Arch, s *sym.Symbol) int {
-	return int(decodeInuxi(arch, s.P[commonsize(arch)+2*arch.PtrSize:], arch.PtrSize))
-}
-
-func decodetypeStructFieldArrayOff(arch *sys.Arch, s *sym.Symbol, i int) int {
-	off := commonsize(arch) + 4*arch.PtrSize
-	if decodetypeHasUncommon(arch, s.P) {
-		off += uncommonSize()
-	}
-	off += i * structfieldSize(arch)
-	return off
-}
-
-// decodetypeStr returns the contents of an rtype's str field (a nameOff).
-func decodetypeStr(arch *sys.Arch, s *sym.Symbol) string {
-	str := decodetypeName(s, 4*arch.PtrSize+8)
-	if s.P[2*arch.PtrSize+4]&tflagExtraStar != 0 {
-		return str[1:]
-	}
-	return str
-}
-
-// decodetypeName decodes the name from a reflect.name.
-func decodetypeName(s *sym.Symbol, off int) string {
-	r := decodeReloc(s, int32(off))
-	if r == nil {
-		return ""
-	}
-
-	data := r.Sym.P
-	namelen := int(uint16(data[1])<<8 | uint16(data[2]))
-	return string(data[3 : 3+namelen])
-}
-
-func decodetypeStructFieldName(arch *sys.Arch, s *sym.Symbol, i int) string {
-	off := decodetypeStructFieldArrayOff(arch, s, i)
-	return decodetypeName(s, off)
-}
-
-func decodetypeStructFieldType(arch *sys.Arch, s *sym.Symbol, i int) *sym.Symbol {
-	off := decodetypeStructFieldArrayOff(arch, s, i)
-	return decodeRelocSym(s, int32(off+arch.PtrSize))
-}
-
-func decodetypeStructFieldOffs(arch *sys.Arch, s *sym.Symbol, i int) int64 {
-	return decodetypeStructFieldOffsAnon(arch, s, i) >> 1
-}
-
-func decodetypeStructFieldOffsAnon(arch *sys.Arch, s *sym.Symbol, i int) int64 {
-	off := decodetypeStructFieldArrayOff(arch, s, i)
-	return int64(decodeInuxi(arch, s.P[off+2*arch.PtrSize:], arch.PtrSize))
-}
-
-// InterfaceType.methods.length
-func decodetypeIfaceMethodCount(arch *sys.Arch, p []byte) int64 {
-	return int64(decodeInuxi(arch, p[commonsize(arch)+2*arch.PtrSize:], arch.PtrSize))
-}
-
-// methodsig is a fully qualified typed method signature, like
-// "Visit(type.go/ast.Node) (type.go/ast.Visitor)".
-type methodsig string
-
-// Matches runtime/typekind.go and reflect.Kind.
-const (
-	kindArray     = 17
-	kindChan      = 18
-	kindFunc      = 19
-	kindInterface = 20
-	kindMap       = 21
-	kindPtr       = 22
-	kindSlice     = 23
-	kindStruct    = 25
-	kindMask      = (1 << 5) - 1
-)
-
-// decodeMethodSig decodes an array of method signature information.
-// Each element of the array is size bytes. The first 4 bytes is a
-// nameOff for the method name, and the next 4 bytes is a typeOff for
-// the function type.
-//
-// Conveniently this is the layout of both runtime.method and runtime.imethod.
-func decodeMethodSig(arch *sys.Arch, s *sym.Symbol, off, size, count int) []methodsig {
-	var buf bytes.Buffer
-	var methods []methodsig
-	for i := 0; i < count; i++ {
-		buf.WriteString(decodetypeName(s, off))
-		mtypSym := decodeRelocSym(s, int32(off+4))
-
-		buf.WriteRune('(')
-		inCount := decodetypeFuncInCount(arch, mtypSym.P)
-		for i := 0; i < inCount; i++ {
-			if i > 0 {
-				buf.WriteString(", ")
-			}
-			buf.WriteString(decodetypeFuncInType(arch, mtypSym, i).Name)
-		}
-		buf.WriteString(") (")
-		outCount := decodetypeFuncOutCount(arch, mtypSym.P)
-		for i := 0; i < outCount; i++ {
-			if i > 0 {
-				buf.WriteString(", ")
-			}
-			buf.WriteString(decodetypeFuncOutType(arch, mtypSym, i).Name)
-		}
-		buf.WriteRune(')')
-
-		off += size
-		methods = append(methods, methodsig(buf.String()))
-		buf.Reset()
-	}
-	return methods
-}
-
-func decodeIfaceMethods(arch *sys.Arch, s *sym.Symbol) []methodsig {
-	if decodetypeKind(arch, s.P)&kindMask != kindInterface {
-		panic(fmt.Sprintf("symbol %q is not an interface", s.Name))
-	}
-	r := decodeReloc(s, int32(commonsize(arch)+arch.PtrSize))
-	if r == nil {
-		return nil
-	}
-	if r.Sym != s {
-		panic(fmt.Sprintf("imethod slice pointer in %q leads to a different symbol", s.Name))
-	}
-	off := int(r.Add) // array of reflect.imethod values
-	numMethods := int(decodetypeIfaceMethodCount(arch, s.P))
-	sizeofIMethod := 4 + 4
-	return decodeMethodSig(arch, s, off, sizeofIMethod, numMethods)
-}
-
-func decodetypeMethods(arch *sys.Arch, s *sym.Symbol) []methodsig {
-	if !decodetypeHasUncommon(arch, s.P) {
-		panic(fmt.Sprintf("no methods on %q", s.Name))
-	}
-	off := commonsize(arch) // reflect.rtype
-	switch decodetypeKind(arch, s.P) & kindMask {
-	case kindStruct: // reflect.structType
-		off += 4 * arch.PtrSize
-	case kindPtr: // reflect.ptrType
-		off += arch.PtrSize
-	case kindFunc: // reflect.funcType
-		off += arch.PtrSize // 4 bytes, pointer aligned
-	case kindSlice: // reflect.sliceType
-		off += arch.PtrSize
-	case kindArray: // reflect.arrayType
-		off += 3 * arch.PtrSize
-	case kindChan: // reflect.chanType
-		off += 2 * arch.PtrSize
-	case kindMap: // reflect.mapType
-		off += 4*arch.PtrSize + 8
-	case kindInterface: // reflect.interfaceType
-		off += 3 * arch.PtrSize
-	default:
-		// just Sizeof(rtype)
-	}
-
-	mcount := int(decodeInuxi(arch, s.P[off+4:], 2))
-	moff := int(decodeInuxi(arch, s.P[off+4+2+2:], 4))
-	off += moff                // offset to array of reflect.method values
-	const sizeofMethod = 4 * 4 // sizeof reflect.method in program
-	return decodeMethodSig(arch, s, off, sizeofMethod, mcount)
-}
diff --git a/src/cmd/oldlink/internal/ld/dwarf.go b/src/cmd/oldlink/internal/ld/dwarf.go
deleted file mode 100644
index 3d5220c..0000000
--- a/src/cmd/oldlink/internal/ld/dwarf.go
+++ /dev/null
@@ -1,2044 +0,0 @@
-// Copyright 2010 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.
-
-// TODO/NICETOHAVE:
-//   - eliminate DW_CLS_ if not used
-//   - package info in compilation units
-//   - assign types to their packages
-//   - gdb uses c syntax, meaning clumsy quoting is needed for go identifiers. eg
-//     ptype struct '[]uint8' and qualifiers need to be quoted away
-//   - file:line info for variables
-//   - make strings a typedef so prettyprinters can see the underlying string type
-
-package ld
-
-import (
-	"cmd/internal/dwarf"
-	"cmd/internal/obj"
-	"cmd/internal/objabi"
-	"cmd/internal/src"
-	"cmd/internal/sys"
-	"cmd/oldlink/internal/sym"
-	"fmt"
-	"log"
-	"sort"
-	"strings"
-)
-
-type dwctxt struct {
-	linkctxt *Link
-}
-
-func (c dwctxt) PtrSize() int {
-	return c.linkctxt.Arch.PtrSize
-}
-func (c dwctxt) AddInt(s dwarf.Sym, size int, i int64) {
-	ls := s.(*sym.Symbol)
-	ls.AddUintXX(c.linkctxt.Arch, uint64(i), size)
-}
-func (c dwctxt) AddBytes(s dwarf.Sym, b []byte) {
-	ls := s.(*sym.Symbol)
-	ls.AddBytes(b)
-}
-func (c dwctxt) AddString(s dwarf.Sym, v string) {
-	Addstring(s.(*sym.Symbol), v)
-}
-
-func (c dwctxt) AddAddress(s dwarf.Sym, data interface{}, value int64) {
-	if value != 0 {
-		value -= (data.(*sym.Symbol)).Value
-	}
-	s.(*sym.Symbol).AddAddrPlus(c.linkctxt.Arch, data.(*sym.Symbol), value)
-}
-
-func (c dwctxt) AddCURelativeAddress(s dwarf.Sym, data interface{}, value int64) {
-	if value != 0 {
-		value -= (data.(*sym.Symbol)).Value
-	}
-	s.(*sym.Symbol).AddCURelativeAddrPlus(c.linkctxt.Arch, data.(*sym.Symbol), value)
-}
-
-func (c dwctxt) AddSectionOffset(s dwarf.Sym, size int, t interface{}, ofs int64) {
-	ls := s.(*sym.Symbol)
-	switch size {
-	default:
-		Errorf(ls, "invalid size %d in adddwarfref\n", size)
-		fallthrough
-	case c.linkctxt.Arch.PtrSize:
-		ls.AddAddr(c.linkctxt.Arch, t.(*sym.Symbol))
-	case 4:
-		ls.AddAddrPlus4(t.(*sym.Symbol), 0)
-	}
-	r := &ls.R[len(ls.R)-1]
-	r.Type = objabi.R_ADDROFF
-	r.Add = ofs
-}
-
-func (c dwctxt) AddDWARFAddrSectionOffset(s dwarf.Sym, t interface{}, ofs int64) {
-	size := 4
-	if isDwarf64(c.linkctxt) {
-		size = 8
-	}
-
-	c.AddSectionOffset(s, size, t, ofs)
-	ls := s.(*sym.Symbol)
-	ls.R[len(ls.R)-1].Type = objabi.R_DWARFSECREF
-}
-
-func (c dwctxt) Logf(format string, args ...interface{}) {
-	c.linkctxt.Logf(format, args...)
-}
-
-// At the moment these interfaces are only used in the compiler.
-
-func (c dwctxt) AddFileRef(s dwarf.Sym, f interface{}) {
-	panic("should be used only in the compiler")
-}
-
-func (c dwctxt) CurrentOffset(s dwarf.Sym) int64 {
-	panic("should be used only in the compiler")
-}
-
-func (c dwctxt) RecordDclReference(s dwarf.Sym, t dwarf.Sym, dclIdx int, inlIndex int) {
-	panic("should be used only in the compiler")
-}
-
-func (c dwctxt) RecordChildDieOffsets(s dwarf.Sym, vars []*dwarf.Var, offsets []int32) {
-	panic("should be used only in the compiler")
-}
-
-func isDwarf64(ctxt *Link) bool {
-	return ctxt.HeadType == objabi.Haix
-}
-
-var gdbscript string
-
-var dwarfp []*sym.Symbol
-
-func writeabbrev(ctxt *Link) *sym.Symbol {
-	s := ctxt.Syms.Lookup(".debug_abbrev", 0)
-	s.Type = sym.SDWARFSECT
-	s.AddBytes(dwarf.GetAbbrev())
-	return s
-}
-
-var dwtypes dwarf.DWDie
-
-func newattr(die *dwarf.DWDie, attr uint16, cls int, value int64, data interface{}) *dwarf.DWAttr {
-	a := new(dwarf.DWAttr)
-	a.Link = die.Attr
-	die.Attr = a
-	a.Atr = attr
-	a.Cls = uint8(cls)
-	a.Value = value
-	a.Data = data
-	return a
-}
-
-// Each DIE (except the root ones) has at least 1 attribute: its
-// name. getattr moves the desired one to the front so
-// frequently searched ones are found faster.
-func getattr(die *dwarf.DWDie, attr uint16) *dwarf.DWAttr {
-	if die.Attr.Atr == attr {
-		return die.Attr
-	}
-
-	a := die.Attr
-	b := a.Link
-	for b != nil {
-		if b.Atr == attr {
-			a.Link = b.Link
-			b.Link = die.Attr
-			die.Attr = b
-			return b
-		}
-
-		a = b
-		b = b.Link
-	}
-
-	return nil
-}
-
-// Every DIE manufactured by the linker has at least an AT_name
-// attribute (but it will only be written out if it is listed in the abbrev).
-// The compiler does create nameless DWARF DIEs (ex: concrete subprogram
-// instance).
-func newdie(ctxt *Link, parent *dwarf.DWDie, abbrev int, name string, version int) *dwarf.DWDie {
-	die := new(dwarf.DWDie)
-	die.Abbrev = abbrev
-	die.Link = parent.Child
-	parent.Child = die
-
-	newattr(die, dwarf.DW_AT_name, dwarf.DW_CLS_STRING, int64(len(name)), name)
-
-	if name != "" && (abbrev <= dwarf.DW_ABRV_VARIABLE || abbrev >= dwarf.DW_ABRV_NULLTYPE) {
-		if abbrev != dwarf.DW_ABRV_VARIABLE || version == 0 {
-			if abbrev == dwarf.DW_ABRV_COMPUNIT {
-				// Avoid collisions with "real" symbol names.
-				name = fmt.Sprintf(".pkg.%s.%d", name, len(ctxt.compUnits))
-			}
-			s := ctxt.Syms.Lookup(dwarf.InfoPrefix+name, version)
-			s.Attr |= sym.AttrNotInSymbolTable
-			s.Type = sym.SDWARFINFO
-			die.Sym = s
-		}
-	}
-
-	return die
-}
-
-func walktypedef(die *dwarf.DWDie) *dwarf.DWDie {
-	if die == nil {
-		return nil
-	}
-	// Resolve typedef if present.
-	if die.Abbrev == dwarf.DW_ABRV_TYPEDECL {
-		for attr := die.Attr; attr != nil; attr = attr.Link {
-			if attr.Atr == dwarf.DW_AT_type && attr.Cls == dwarf.DW_CLS_REFERENCE && attr.Data != nil {
-				return attr.Data.(*dwarf.DWDie)
-			}
-		}
-	}
-
-	return die
-}
-
-func walksymtypedef(ctxt *Link, s *sym.Symbol) *sym.Symbol {
-	if t := ctxt.Syms.ROLookup(s.Name+"..def", int(s.Version)); t != nil {
-		return t
-	}
-	return s
-}
-
-// Find child by AT_name using hashtable if available or linear scan
-// if not.
-func findchild(die *dwarf.DWDie, name string) *dwarf.DWDie {
-	var prev *dwarf.DWDie
-	for ; die != prev; prev, die = die, walktypedef(die) {
-		for a := die.Child; a != nil; a = a.Link {
-			if name == getattr(a, dwarf.DW_AT_name).Data {
-				return a
-			}
-		}
-		continue
-	}
-	return nil
-}
-
-// Used to avoid string allocation when looking up dwarf symbols
-var prefixBuf = []byte(dwarf.InfoPrefix)
-
-func find(ctxt *Link, name string) *sym.Symbol {
-	n := append(prefixBuf, name...)
-	// The string allocation below is optimized away because it is only used in a map lookup.
-	s := ctxt.Syms.ROLookup(string(n), 0)
-	prefixBuf = n[:len(dwarf.InfoPrefix)]
-	if s != nil && s.Type == sym.SDWARFINFO {
-		return s
-	}
-	return nil
-}
-
-func mustFind(ctxt *Link, name string) *sym.Symbol {
-	r := find(ctxt, name)
-	if r == nil {
-		Exitf("dwarf find: cannot find %s", name)
-	}
-	return r
-}
-
-func adddwarfref(ctxt *Link, s *sym.Symbol, t *sym.Symbol, size int) int64 {
-	var result int64
-	switch size {
-	default:
-		Errorf(s, "invalid size %d in adddwarfref\n", size)
-		fallthrough
-	case ctxt.Arch.PtrSize:
-		result = s.AddAddr(ctxt.Arch, t)
-	case 4:
-		result = s.AddAddrPlus4(t, 0)
-	}
-	r := &s.R[len(s.R)-1]
-	r.Type = objabi.R_DWARFSECREF
-	return result
-}
-
-func newrefattr(die *dwarf.DWDie, attr uint16, ref *sym.Symbol) *dwarf.DWAttr {
-	if ref == nil {
-		return nil
-	}
-	return newattr(die, attr, dwarf.DW_CLS_REFERENCE, 0, ref)
-}
-
-func dtolsym(s dwarf.Sym) *sym.Symbol {
-	if s == nil {
-		return nil
-	}
-	return s.(*sym.Symbol)
-}
-
-func putdie(linkctxt *Link, ctxt dwarf.Context, syms []*sym.Symbol, die *dwarf.DWDie) []*sym.Symbol {
-	s := dtolsym(die.Sym)
-	if s == nil {
-		s = syms[len(syms)-1]
-	} else {
-		if s.Attr.OnList() {
-			log.Fatalf("symbol %s listed multiple times", s.Name)
-		}
-		s.Attr |= sym.AttrOnList
-		syms = append(syms, s)
-	}
-	dwarf.Uleb128put(ctxt, s, int64(die.Abbrev))
-	dwarf.PutAttrs(ctxt, s, die.Abbrev, die.Attr)
-	if dwarf.HasChildren(die) {
-		for die := die.Child; die != nil; die = die.Link {
-			syms = putdie(linkctxt, ctxt, syms, die)
-		}
-		syms[len(syms)-1].AddUint8(0)
-	}
-	return syms
-}
-
-func reverselist(list **dwarf.DWDie) {
-	curr := *list
-	var prev *dwarf.DWDie
-	for curr != nil {
-		next := curr.Link
-		curr.Link = prev
-		prev = curr
-		curr = next
-	}
-
-	*list = prev
-}
-
-func reversetree(list **dwarf.DWDie) {
-	reverselist(list)
-	for die := *list; die != nil; die = die.Link {
-		if dwarf.HasChildren(die) {
-			reversetree(&die.Child)
-		}
-	}
-}
-
-func newmemberoffsetattr(die *dwarf.DWDie, offs int32) {
-	newattr(die, dwarf.DW_AT_data_member_location, dwarf.DW_CLS_CONSTANT, int64(offs), nil)
-}
-
-// GDB doesn't like FORM_addr for AT_location, so emit a
-// location expression that evals to a const.
-func newabslocexprattr(die *dwarf.DWDie, addr int64, sym *sym.Symbol) {
-	newattr(die, dwarf.DW_AT_location, dwarf.DW_CLS_ADDRESS, addr, sym)
-	// below
-}
-
-// Lookup predefined types
-func lookupOrDiag(ctxt *Link, n string) *sym.Symbol {
-	s := ctxt.Syms.ROLookup(n, 0)
-	if s == nil || s.Size == 0 {
-		Exitf("dwarf: missing type: %s", n)
-	}
-
-	return s
-}
-
-// dwarfFuncSym looks up a DWARF metadata symbol for function symbol s.
-// If the symbol does not exist, it creates it if create is true,
-// or returns nil otherwise.
-func dwarfFuncSym(ctxt *Link, s *sym.Symbol, meta string, create bool) *sym.Symbol {
-	// All function ABIs use symbol version 0 for the DWARF data.
-	//
-	// TODO(austin): It may be useful to have DWARF info for ABI
-	// wrappers, in which case we may want these versions to
-	// align. Better yet, replace these name lookups with a
-	// general way to attach metadata to a symbol.
-	ver := 0
-	if s.IsFileLocal() {
-		ver = int(s.Version)
-	}
-	if create {
-		return ctxt.Syms.Lookup(meta+s.Name, ver)
-	}
-	return ctxt.Syms.ROLookup(meta+s.Name, ver)
-}
-
-func dotypedef(ctxt *Link, parent *dwarf.DWDie, name string, def *dwarf.DWDie) *dwarf.DWDie {
-	// Only emit typedefs for real names.
-	if strings.HasPrefix(name, "map[") {
-		return nil
-	}
-	if strings.HasPrefix(name, "struct {") {
-		return nil
-	}
-	if strings.HasPrefix(name, "chan ") {
-		return nil
-	}
-	if name[0] == '[' || name[0] == '*' {
-		return nil
-	}
-	if def == nil {
-		Errorf(nil, "dwarf: bad def in dotypedef")
-	}
-
-	s := ctxt.Syms.Lookup(dtolsym(def.Sym).Name+"..def", 0)
-	s.Attr |= sym.AttrNotInSymbolTable
-	s.Type = sym.SDWARFINFO
-	def.Sym = s
-
-	// The typedef entry must be created after the def,
-	// so that future lookups will find the typedef instead
-	// of the real definition. This hooks the typedef into any
-	// circular definition loops, so that gdb can understand them.
-	die := newdie(ctxt, parent, dwarf.DW_ABRV_TYPEDECL, name, 0)
-
-	newrefattr(die, dwarf.DW_AT_type, s)
-
-	return die
-}
-
-// Define gotype, for composite ones recurse into constituents.
-func defgotype(ctxt *Link, gotype *sym.Symbol) *sym.Symbol {
-	if gotype == nil {
-		return mustFind(ctxt, "<unspecified>")
-	}
-
-	if !strings.HasPrefix(gotype.Name, "type.") {
-		Errorf(gotype, "dwarf: type name doesn't start with \"type.\"")
-		return mustFind(ctxt, "<unspecified>")
-	}
-
-	name := gotype.Name[5:] // could also decode from Type.string
-
-	sdie := find(ctxt, name)
-
-	if sdie != nil {
-		return sdie
-	}
-
-	return newtype(ctxt, gotype).Sym.(*sym.Symbol)
-}
-
-func newtype(ctxt *Link, gotype *sym.Symbol) *dwarf.DWDie {
-	name := gotype.Name[5:] // could also decode from Type.string
-	kind := decodetypeKind(ctxt.Arch, gotype.P)
-	bytesize := decodetypeSize(ctxt.Arch, gotype.P)
-
-	var die, typedefdie *dwarf.DWDie
-	switch kind {
-	case objabi.KindBool:
-		die = newdie(ctxt, &dwtypes, dwarf.DW_ABRV_BASETYPE, name, 0)
-		newattr(die, dwarf.DW_AT_encoding, dwarf.DW_CLS_CONSTANT, dwarf.DW_ATE_boolean, 0)
-		newattr(die, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, bytesize, 0)
-
-	case objabi.KindInt,
-		objabi.KindInt8,
-		objabi.KindInt16,
-		objabi.KindInt32,
-		objabi.KindInt64:
-		die = newdie(ctxt, &dwtypes, dwarf.DW_ABRV_BASETYPE, name, 0)
-		newattr(die, dwarf.DW_AT_encoding, dwarf.DW_CLS_CONSTANT, dwarf.DW_ATE_signed, 0)
-		newattr(die, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, bytesize, 0)
-
-	case objabi.KindUint,
-		objabi.KindUint8,
-		objabi.KindUint16,
-		objabi.KindUint32,
-		objabi.KindUint64,
-		objabi.KindUintptr:
-		die = newdie(ctxt, &dwtypes, dwarf.DW_ABRV_BASETYPE, name, 0)
-		newattr(die, dwarf.DW_AT_encoding, dwarf.DW_CLS_CONSTANT, dwarf.DW_ATE_unsigned, 0)
-		newattr(die, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, bytesize, 0)
-
-	case objabi.KindFloat32,
-		objabi.KindFloat64:
-		die = newdie(ctxt, &dwtypes, dwarf.DW_ABRV_BASETYPE, name, 0)
-		newattr(die, dwarf.DW_AT_encoding, dwarf.DW_CLS_CONSTANT, dwarf.DW_ATE_float, 0)
-		newattr(die, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, bytesize, 0)
-
-	case objabi.KindComplex64,
-		objabi.KindComplex128:
-		die = newdie(ctxt, &dwtypes, dwarf.DW_ABRV_BASETYPE, name, 0)
-		newattr(die, dwarf.DW_AT_encoding, dwarf.DW_CLS_CONSTANT, dwarf.DW_ATE_complex_float, 0)
-		newattr(die, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, bytesize, 0)
-
-	case objabi.KindArray:
-		die = newdie(ctxt, &dwtypes, dwarf.DW_ABRV_ARRAYTYPE, name, 0)
-		typedefdie = dotypedef(ctxt, &dwtypes, name, die)
-		newattr(die, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, bytesize, 0)
-		s := decodetypeArrayElem(ctxt.Arch, gotype)
-		newrefattr(die, dwarf.DW_AT_type, defgotype(ctxt, s))
-		fld := newdie(ctxt, die, dwarf.DW_ABRV_ARRAYRANGE, "range", 0)
-
-		// use actual length not upper bound; correct for 0-length arrays.
-		newattr(fld, dwarf.DW_AT_count, dwarf.DW_CLS_CONSTANT, decodetypeArrayLen(ctxt.Arch, gotype), 0)
-
-		newrefattr(fld, dwarf.DW_AT_type, mustFind(ctxt, "uintptr"))
-
-	case objabi.KindChan:
-		die = newdie(ctxt, &dwtypes, dwarf.DW_ABRV_CHANTYPE, name, 0)
-		s := decodetypeChanElem(ctxt.Arch, gotype)
-		newrefattr(die, dwarf.DW_AT_go_elem, defgotype(ctxt, s))
-		// Save elem type for synthesizechantypes. We could synthesize here
-		// but that would change the order of DIEs we output.
-		newrefattr(die, dwarf.DW_AT_type, s)
-
-	case objabi.KindFunc:
-		die = newdie(ctxt, &dwtypes, dwarf.DW_ABRV_FUNCTYPE, name, 0)
-		newattr(die, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, bytesize, 0)
-		typedefdie = dotypedef(ctxt, &dwtypes, name, die)
-		nfields := decodetypeFuncInCount(ctxt.Arch, gotype.P)
-		for i := 0; i < nfields; i++ {
-			s := decodetypeFuncInType(ctxt.Arch, gotype, i)
-			fld := newdie(ctxt, die, dwarf.DW_ABRV_FUNCTYPEPARAM, s.Name[5:], 0)
-			newrefattr(fld, dwarf.DW_AT_type, defgotype(ctxt, s))
-		}
-
-		if decodetypeFuncDotdotdot(ctxt.Arch, gotype.P) {
-			newdie(ctxt, die, dwarf.DW_ABRV_DOTDOTDOT, "...", 0)
-		}
-		nfields = decodetypeFuncOutCount(ctxt.Arch, gotype.P)
-		for i := 0; i < nfields; i++ {
-			s := decodetypeFuncOutType(ctxt.Arch, gotype, i)
-			fld := newdie(ctxt, die, dwarf.DW_ABRV_FUNCTYPEPARAM, s.Name[5:], 0)
-			newrefattr(fld, dwarf.DW_AT_type, defptrto(ctxt, defgotype(ctxt, s)))
-		}
-
-	case objabi.KindInterface:
-		die = newdie(ctxt, &dwtypes, dwarf.DW_ABRV_IFACETYPE, name, 0)
-		typedefdie = dotypedef(ctxt, &dwtypes, name, die)
-		nfields := int(decodetypeIfaceMethodCount(ctxt.Arch, gotype.P))
-		var s *sym.Symbol
-		if nfields == 0 {
-			s = lookupOrDiag(ctxt, "type.runtime.eface")
-		} else {
-			s = lookupOrDiag(ctxt, "type.runtime.iface")
-		}
-		newrefattr(die, dwarf.DW_AT_type, defgotype(ctxt, s))
-
-	case objabi.KindMap:
-		die = newdie(ctxt, &dwtypes, dwarf.DW_ABRV_MAPTYPE, name, 0)
-		s := decodetypeMapKey(ctxt.Arch, gotype)
-		newrefattr(die, dwarf.DW_AT_go_key, defgotype(ctxt, s))
-		s = decodetypeMapValue(ctxt.Arch, gotype)
-		newrefattr(die, dwarf.DW_AT_go_elem, defgotype(ctxt, s))
-		// Save gotype for use in synthesizemaptypes. We could synthesize here,
-		// but that would change the order of the DIEs.
-		newrefattr(die, dwarf.DW_AT_type, gotype)
-
-	case objabi.KindPtr:
-		die = newdie(ctxt, &dwtypes, dwarf.DW_ABRV_PTRTYPE, name, 0)
-		typedefdie = dotypedef(ctxt, &dwtypes, name, die)
-		s := decodetypePtrElem(ctxt.Arch, gotype)
-		newrefattr(die, dwarf.DW_AT_type, defgotype(ctxt, s))
-
-	case objabi.KindSlice:
-		die = newdie(ctxt, &dwtypes, dwarf.DW_ABRV_SLICETYPE, name, 0)
-		typedefdie = dotypedef(ctxt, &dwtypes, name, die)
-		newattr(die, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, bytesize, 0)
-		s := decodetypeArrayElem(ctxt.Arch, gotype)
-		elem := defgotype(ctxt, s)
-		newrefattr(die, dwarf.DW_AT_go_elem, elem)
-
-	case objabi.KindString:
-		die = newdie(ctxt, &dwtypes, dwarf.DW_ABRV_STRINGTYPE, name, 0)
-		newattr(die, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, bytesize, 0)
-
-	case objabi.KindStruct:
-		die = newdie(ctxt, &dwtypes, dwarf.DW_ABRV_STRUCTTYPE, name, 0)
-		typedefdie = dotypedef(ctxt, &dwtypes, name, die)
-		newattr(die, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, bytesize, 0)
-		nfields := decodetypeStructFieldCount(ctxt.Arch, gotype)
-		for i := 0; i < nfields; i++ {
-			f := decodetypeStructFieldName(ctxt.Arch, gotype, i)
-			s := decodetypeStructFieldType(ctxt.Arch, gotype, i)
-			if f == "" {
-				f = s.Name[5:] // skip "type."
-			}
-			fld := newdie(ctxt, die, dwarf.DW_ABRV_STRUCTFIELD, f, 0)
-			newrefattr(fld, dwarf.DW_AT_type, defgotype(ctxt, s))
-			offsetAnon := decodetypeStructFieldOffsAnon(ctxt.Arch, gotype, i)
-			newmemberoffsetattr(fld, int32(offsetAnon>>1))
-			if offsetAnon&1 != 0 { // is embedded field
-				newattr(fld, dwarf.DW_AT_go_embedded_field, dwarf.DW_CLS_FLAG, 1, 0)
-			}
-		}
-
-	case objabi.KindUnsafePointer:
-		die = newdie(ctxt, &dwtypes, dwarf.DW_ABRV_BARE_PTRTYPE, name, 0)
-
-	default:
-		Errorf(gotype, "dwarf: definition of unknown kind %d", kind)
-		die = newdie(ctxt, &dwtypes, dwarf.DW_ABRV_TYPEDECL, name, 0)
-		newrefattr(die, dwarf.DW_AT_type, mustFind(ctxt, "<unspecified>"))
-	}
-
-	newattr(die, dwarf.DW_AT_go_kind, dwarf.DW_CLS_CONSTANT, int64(kind), 0)
-	if gotype.Attr.Reachable() {
-		newattr(die, dwarf.DW_AT_go_runtime_type, dwarf.DW_CLS_GO_TYPEREF, 0, gotype)
-	}
-
-	if _, ok := prototypedies[gotype.Name]; ok {
-		prototypedies[gotype.Name] = die
-	}
-
-	if typedefdie != nil {
-		return typedefdie
-	}
-	return die
-}
-
-func nameFromDIESym(dwtype *sym.Symbol) string {
-	return strings.TrimSuffix(dwtype.Name[len(dwarf.InfoPrefix):], "..def")
-}
-
-// Find or construct *T given T.
-func defptrto(ctxt *Link, dwtype *sym.Symbol) *sym.Symbol {
-	ptrname := "*" + nameFromDIESym(dwtype)
-	if die := find(ctxt, ptrname); die != nil {
-		return die
-	}
-
-	pdie := newdie(ctxt, &dwtypes, dwarf.DW_ABRV_PTRTYPE, ptrname, 0)
-	newrefattr(pdie, dwarf.DW_AT_type, dwtype)
-
-	// The DWARF info synthesizes pointer types that don't exist at the
-	// language level, like *hash<...> and *bucket<...>, and the data
-	// pointers of slices. Link to the ones we can find.
-	gotype := ctxt.Syms.ROLookup("type."+ptrname, 0)
-	if gotype != nil && gotype.Attr.Reachable() {
-		newattr(pdie, dwarf.DW_AT_go_runtime_type, dwarf.DW_CLS_GO_TYPEREF, 0, gotype)
-	}
-	return dtolsym(pdie.Sym)
-}
-
-// Copies src's children into dst. Copies attributes by value.
-// DWAttr.data is copied as pointer only. If except is one of
-// the top-level children, it will not be copied.
-func copychildrenexcept(ctxt *Link, dst *dwarf.DWDie, src *dwarf.DWDie, except *dwarf.DWDie) {
-	for src = src.Child; src != nil; src = src.Link {
-		if src == except {
-			continue
-		}
-		c := newdie(ctxt, dst, src.Abbrev, getattr(src, dwarf.DW_AT_name).Data.(string), 0)
-		for a := src.Attr; a != nil; a = a.Link {
-			newattr(c, a.Atr, int(a.Cls), a.Value, a.Data)
-		}
-		copychildrenexcept(ctxt, c, src, nil)
-	}
-
-	reverselist(&dst.Child)
-}
-
-func copychildren(ctxt *Link, dst *dwarf.DWDie, src *dwarf.DWDie) {
-	copychildrenexcept(ctxt, dst, src, nil)
-}
-
-// Search children (assumed to have TAG_member) for the one named
-// field and set its AT_type to dwtype
-func substitutetype(structdie *dwarf.DWDie, field string, dwtype *sym.Symbol) {
-	child := findchild(structdie, field)
-	if child == nil {
-		Exitf("dwarf substitutetype: %s does not have member %s",
-			getattr(structdie, dwarf.DW_AT_name).Data, field)
-		return
-	}
-
-	a := getattr(child, dwarf.DW_AT_type)
-	if a != nil {
-		a.Data = dwtype
-	} else {
-		newrefattr(child, dwarf.DW_AT_type, dwtype)
-	}
-}
-
-func findprotodie(ctxt *Link, name string) *dwarf.DWDie {
-	die, ok := prototypedies[name]
-	if ok && die == nil {
-		defgotype(ctxt, lookupOrDiag(ctxt, name))
-		die = prototypedies[name]
-	}
-	return die
-}
-
-func synthesizestringtypes(ctxt *Link, die *dwarf.DWDie) {
-	prototype := walktypedef(findprotodie(ctxt, "type.runtime.stringStructDWARF"))
-	if prototype == nil {
-		return
-	}
-
-	for ; die != nil; die = die.Link {
-		if die.Abbrev != dwarf.DW_ABRV_STRINGTYPE {
-			continue
-		}
-		copychildren(ctxt, die, prototype)
-	}
-}
-
-func synthesizeslicetypes(ctxt *Link, die *dwarf.DWDie) {
-	prototype := walktypedef(findprotodie(ctxt, "type.runtime.slice"))
-	if prototype == nil {
-		return
-	}
-
-	for ; die != nil; die = die.Link {
-		if die.Abbrev != dwarf.DW_ABRV_SLICETYPE {
-			continue
-		}
-		copychildren(ctxt, die, prototype)
-		elem := getattr(die, dwarf.DW_AT_go_elem).Data.(*sym.Symbol)
-		substitutetype(die, "array", defptrto(ctxt, elem))
-	}
-}
-
-func mkinternaltypename(base string, arg1 string, arg2 string) string {
-	if arg2 == "" {
-		return fmt.Sprintf("%s<%s>", base, arg1)
-	}
-	return fmt.Sprintf("%s<%s,%s>", base, arg1, arg2)
-}
-
-// synthesizemaptypes is way too closely married to runtime/hashmap.c
-const (
-	MaxKeySize = 128
-	MaxValSize = 128
-	BucketSize = 8
-)
-
-func mkinternaltype(ctxt *Link, abbrev int, typename, keyname, valname string, f func(*dwarf.DWDie)) *sym.Symbol {
-	name := mkinternaltypename(typename, keyname, valname)
-	symname := dwarf.InfoPrefix + name
-	s := ctxt.Syms.ROLookup(symname, 0)
-	if s != nil && s.Type == sym.SDWARFINFO {
-		return s
-	}
-	die := newdie(ctxt, &dwtypes, abbrev, name, 0)
-	f(die)
-	return dtolsym(die.Sym)
-}
-
-func synthesizemaptypes(ctxt *Link, die *dwarf.DWDie) {
-	hash := walktypedef(findprotodie(ctxt, "type.runtime.hmap"))
-	bucket := walktypedef(findprotodie(ctxt, "type.runtime.bmap"))
-
-	if hash == nil {
-		return
-	}
-
-	for ; die != nil; die = die.Link {
-		if die.Abbrev != dwarf.DW_ABRV_MAPTYPE {
-			continue
-		}
-		gotype := getattr(die, dwarf.DW_AT_type).Data.(*sym.Symbol)
-		keytype := decodetypeMapKey(ctxt.Arch, gotype)
-		valtype := decodetypeMapValue(ctxt.Arch, gotype)
-		keysize, valsize := decodetypeSize(ctxt.Arch, keytype.P), decodetypeSize(ctxt.Arch, valtype.P)
-		keytype, valtype = walksymtypedef(ctxt, defgotype(ctxt, keytype)), walksymtypedef(ctxt, defgotype(ctxt, valtype))
-
-		// compute size info like hashmap.c does.
-		indirectKey, indirectVal := false, false
-		if keysize > MaxKeySize {
-			keysize = int64(ctxt.Arch.PtrSize)
-			indirectKey = true
-		}
-		if valsize > MaxValSize {
-			valsize = int64(ctxt.Arch.PtrSize)
-			indirectVal = true
-		}
-
-		// Construct type to represent an array of BucketSize keys
-		keyname := nameFromDIESym(keytype)
-		dwhks := mkinternaltype(ctxt, dwarf.DW_ABRV_ARRAYTYPE, "[]key", keyname, "", func(dwhk *dwarf.DWDie) {
-			newattr(dwhk, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, BucketSize*keysize, 0)
-			t := keytype
-			if indirectKey {
-				t = defptrto(ctxt, keytype)
-			}
-			newrefattr(dwhk, dwarf.DW_AT_type, t)
-			fld := newdie(ctxt, dwhk, dwarf.DW_ABRV_ARRAYRANGE, "size", 0)
-			newattr(fld, dwarf.DW_AT_count, dwarf.DW_CLS_CONSTANT, BucketSize, 0)
-			newrefattr(fld, dwarf.DW_AT_type, mustFind(ctxt, "uintptr"))
-		})
-
-		// Construct type to represent an array of BucketSize values
-		valname := nameFromDIESym(valtype)
-		dwhvs := mkinternaltype(ctxt, dwarf.DW_ABRV_ARRAYTYPE, "[]val", valname, "", func(dwhv *dwarf.DWDie) {
-			newattr(dwhv, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, BucketSize*valsize, 0)
-			t := valtype
-			if indirectVal {
-				t = defptrto(ctxt, valtype)
-			}
-			newrefattr(dwhv, dwarf.DW_AT_type, t)
-			fld := newdie(ctxt, dwhv, dwarf.DW_ABRV_ARRAYRANGE, "size", 0)
-			newattr(fld, dwarf.DW_AT_count, dwarf.DW_CLS_CONSTANT, BucketSize, 0)
-			newrefattr(fld, dwarf.DW_AT_type, mustFind(ctxt, "uintptr"))
-		})
-
-		// Construct bucket<K,V>
-		dwhbs := mkinternaltype(ctxt, dwarf.DW_ABRV_STRUCTTYPE, "bucket", keyname, valname, func(dwhb *dwarf.DWDie) {
-			// Copy over all fields except the field "data" from the generic
-			// bucket. "data" will be replaced with keys/values below.
-			copychildrenexcept(ctxt, dwhb, bucket, findchild(bucket, "data"))
-
-			fld := newdie(ctxt, dwhb, dwarf.DW_ABRV_STRUCTFIELD, "keys", 0)
-			newrefattr(fld, dwarf.DW_AT_type, dwhks)
-			newmemberoffsetattr(fld, BucketSize)
-			fld = newdie(ctxt, dwhb, dwarf.DW_ABRV_STRUCTFIELD, "values", 0)
-			newrefattr(fld, dwarf.DW_AT_type, dwhvs)
-			newmemberoffsetattr(fld, BucketSize+BucketSize*int32(keysize))
-			fld = newdie(ctxt, dwhb, dwarf.DW_ABRV_STRUCTFIELD, "overflow", 0)
-			newrefattr(fld, dwarf.DW_AT_type, defptrto(ctxt, dtolsym(dwhb.Sym)))
-			newmemberoffsetattr(fld, BucketSize+BucketSize*(int32(keysize)+int32(valsize)))
-			if ctxt.Arch.RegSize > ctxt.Arch.PtrSize {
-				fld = newdie(ctxt, dwhb, dwarf.DW_ABRV_STRUCTFIELD, "pad", 0)
-				newrefattr(fld, dwarf.DW_AT_type, mustFind(ctxt, "uintptr"))
-				newmemberoffsetattr(fld, BucketSize+BucketSize*(int32(keysize)+int32(valsize))+int32(ctxt.Arch.PtrSize))
-			}
-
-			newattr(dwhb, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, BucketSize+BucketSize*keysize+BucketSize*valsize+int64(ctxt.Arch.RegSize), 0)
-		})
-
-		// Construct hash<K,V>
-		dwhs := mkinternaltype(ctxt, dwarf.DW_ABRV_STRUCTTYPE, "hash", keyname, valname, func(dwh *dwarf.DWDie) {
-			copychildren(ctxt, dwh, hash)
-			substitutetype(dwh, "buckets", defptrto(ctxt, dwhbs))
-			substitutetype(dwh, "oldbuckets", defptrto(ctxt, dwhbs))
-			newattr(dwh, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, getattr(hash, dwarf.DW_AT_byte_size).Value, nil)
-		})
-
-		// make map type a pointer to hash<K,V>
-		newrefattr(die, dwarf.DW_AT_type, defptrto(ctxt, dwhs))
-	}
-}
-
-func synthesizechantypes(ctxt *Link, die *dwarf.DWDie) {
-	sudog := walktypedef(findprotodie(ctxt, "type.runtime.sudog"))
-	waitq := walktypedef(findprotodie(ctxt, "type.runtime.waitq"))
-	hchan := walktypedef(findprotodie(ctxt, "type.runtime.hchan"))
-	if sudog == nil || waitq == nil || hchan == nil {
-		return
-	}
-
-	sudogsize := int(getattr(sudog, dwarf.DW_AT_byte_size).Value)
-
-	for ; die != nil; die = die.Link {
-		if die.Abbrev != dwarf.DW_ABRV_CHANTYPE {
-			continue
-		}
-		elemgotype := getattr(die, dwarf.DW_AT_type).Data.(*sym.Symbol)
-		elemname := elemgotype.Name[5:]
-		elemtype := walksymtypedef(ctxt, defgotype(ctxt, elemgotype))
-
-		// sudog<T>
-		dwss := mkinternaltype(ctxt, dwarf.DW_ABRV_STRUCTTYPE, "sudog", elemname, "", func(dws *dwarf.DWDie) {
-			copychildren(ctxt, dws, sudog)
-			substitutetype(dws, "elem", defptrto(ctxt, elemtype))
-			newattr(dws, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, int64(sudogsize), nil)
-		})
-
-		// waitq<T>
-		dwws := mkinternaltype(ctxt, dwarf.DW_ABRV_STRUCTTYPE, "waitq", elemname, "", func(dww *dwarf.DWDie) {
-
-			copychildren(ctxt, dww, waitq)
-			substitutetype(dww, "first", defptrto(ctxt, dwss))
-			substitutetype(dww, "last", defptrto(ctxt, dwss))
-			newattr(dww, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, getattr(waitq, dwarf.DW_AT_byte_size).Value, nil)
-		})
-
-		// hchan<T>
-		dwhs := mkinternaltype(ctxt, dwarf.DW_ABRV_STRUCTTYPE, "hchan", elemname, "", func(dwh *dwarf.DWDie) {
-			copychildren(ctxt, dwh, hchan)
-			substitutetype(dwh, "recvq", dwws)
-			substitutetype(dwh, "sendq", dwws)
-			newattr(dwh, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, getattr(hchan, dwarf.DW_AT_byte_size).Value, nil)
-		})
-
-		newrefattr(die, dwarf.DW_AT_type, defptrto(ctxt, dwhs))
-	}
-}
-
-func dwarfDefineGlobal(ctxt *Link, s *sym.Symbol, str string, v int64, gotype *sym.Symbol) {
-	// Find a suitable CU DIE to include the global.
-	// One would think it's as simple as just looking at the unit, but that might
-	// not have any reachable code. So, we go to the runtime's CU if our unit
-	// isn't otherwise reachable.
-	var unit *sym.CompilationUnit
-	if s.Unit != nil {
-		unit = s.Unit
-	} else {
-		unit = ctxt.runtimeCU
-	}
-	dv := newdie(ctxt, unit.DWInfo, dwarf.DW_ABRV_VARIABLE, str, int(s.Version))
-	newabslocexprattr(dv, v, s)
-	if !s.IsFileLocal() {
-		newattr(dv, dwarf.DW_AT_external, dwarf.DW_CLS_FLAG, 1, 0)
-	}
-	dt := defgotype(ctxt, gotype)
-	newrefattr(dv, dwarf.DW_AT_type, dt)
-}
-
-// For use with pass.c::genasmsym
-func defdwsymb(ctxt *Link, s *sym.Symbol, str string, t SymbolType, v int64, gotype *sym.Symbol) {
-	if strings.HasPrefix(str, "go.string.") {
-		return
-	}
-	if strings.HasPrefix(str, "runtime.gcbits.") {
-		return
-	}
-
-	switch t {
-	case DataSym, BSSSym:
-		switch s.Type {
-		case sym.SDATA, sym.SNOPTRDATA, sym.STYPE, sym.SBSS, sym.SNOPTRBSS, sym.STLSBSS:
-			// ok
-		case sym.SRODATA:
-			if gotype != nil {
-				defgotype(ctxt, gotype)
-			}
-			return
-		default:
-			return
-		}
-		if ctxt.LinkMode != LinkExternal && isStaticTemp(s.Name) {
-			return
-		}
-		dwarfDefineGlobal(ctxt, s, str, v, gotype)
-
-	case AutoSym, ParamSym, DeletedAutoSym:
-		defgotype(ctxt, gotype)
-	}
-}
-
-// createUnitLength creates the initial length field with value v and update
-// offset of unit_length if needed.
-func createUnitLength(ctxt *Link, s *sym.Symbol, v uint64) {
-	if isDwarf64(ctxt) {
-		s.AddUint32(ctxt.Arch, 0xFFFFFFFF)
-	}
-	addDwarfAddrField(ctxt, s, v)
-}
-
-// addDwarfAddrField adds a DWARF field in DWARF 64bits or 32bits.
-func addDwarfAddrField(ctxt *Link, s *sym.Symbol, v uint64) {
-	if isDwarf64(ctxt) {
-		s.AddUint(ctxt.Arch, v)
-	} else {
-		s.AddUint32(ctxt.Arch, uint32(v))
-	}
-}
-
-// addDwarfAddrRef adds a DWARF pointer in DWARF 64bits or 32bits.
-func addDwarfAddrRef(ctxt *Link, s *sym.Symbol, t *sym.Symbol) {
-	if isDwarf64(ctxt) {
-		adddwarfref(ctxt, s, t, 8)
-	} else {
-		adddwarfref(ctxt, s, t, 4)
-	}
-}
-
-// calcCompUnitRanges calculates the PC ranges of the compilation units.
-func calcCompUnitRanges(ctxt *Link) {
-	var prevUnit *sym.CompilationUnit
-	for _, s := range ctxt.Textp {
-		if s.FuncInfo == nil {
-			continue
-		}
-		// Skip linker-created functions (ex: runtime.addmoduledata), since they
-		// don't have DWARF to begin with.
-		if s.Unit == nil {
-			continue
-		}
-		unit := s.Unit
-		// Update PC ranges.
-		//
-		// We don't simply compare the end of the previous
-		// symbol with the start of the next because there's
-		// often a little padding between them. Instead, we
-		// only create boundaries between symbols from
-		// different units.
-		if prevUnit != unit {
-			unit.PCs = append(unit.PCs, dwarf.Range{Start: s.Value - unit.Textp[0].Value})
-			prevUnit = unit
-		}
-		unit.PCs[len(unit.PCs)-1].End = s.Value - unit.Textp[0].Value + s.Size
-	}
-}
-
-func movetomodule(ctxt *Link, parent *dwarf.DWDie) {
-	die := ctxt.runtimeCU.DWInfo.Child
-	if die == nil {
-		ctxt.runtimeCU.DWInfo.Child = parent.Child
-		return
-	}
-	for die.Link != nil {
-		die = die.Link
-	}
-	die.Link = parent.Child
-}
-
-// If the pcln table contains runtime/proc.go, use that to set gdbscript path.
-func finddebugruntimepath(s *sym.Symbol) {
-	if gdbscript != "" {
-		return
-	}
-
-	for i := range s.FuncInfo.File {
-		f := s.FuncInfo.File[i]
-		// We can't use something that may be dead-code
-		// eliminated from a binary here. proc.go contains
-		// main and the scheduler, so it's not going anywhere.
-		if i := strings.Index(f.Name, "runtime/proc.go"); i >= 0 {
-			gdbscript = f.Name[:i] + "runtime/runtime-gdb.py"
-			break
-		}
-	}
-}
-
-/*
- * Generate a sequence of opcodes that is as short as possible.
- * See section 6.2.5
- */
-const (
-	LINE_BASE   = -4
-	LINE_RANGE  = 10
-	PC_RANGE    = (255 - OPCODE_BASE) / LINE_RANGE
-	OPCODE_BASE = 11
-)
-
-/*
- * Walk prog table, emit line program and build DIE tree.
- */
-
-func getCompilationDir() string {
-	// OSX requires this be set to something, but it's not easy to choose
-	// a value. Linking takes place in a temporary directory, so there's
-	// no point including it here. Paths in the file table are usually
-	// absolute, in which case debuggers will ignore this value. -trimpath
-	// produces relative paths, but we don't know where they start, so
-	// all we can do here is try not to make things worse.
-	return "."
-}
-
-func importInfoSymbol(ctxt *Link, dsym *sym.Symbol) {
-	dsym.Attr |= sym.AttrNotInSymbolTable | sym.AttrReachable
-	dsym.Type = sym.SDWARFINFO
-	for i := range dsym.R {
-		r := &dsym.R[i] // Copying sym.Reloc has measurable impact on performance
-		if r.Type == objabi.R_DWARFSECREF && r.Sym.Size == 0 {
-			n := nameFromDIESym(r.Sym)
-			defgotype(ctxt, ctxt.Syms.Lookup("type."+n, 0))
-		}
-	}
-}
-
-func writelines(ctxt *Link, unit *sym.CompilationUnit, ls *sym.Symbol) {
-
-	var dwarfctxt dwarf.Context = dwctxt{ctxt}
-	is_stmt := uint8(1) // initially = recommended default_is_stmt = 1, tracks is_stmt toggles.
-
-	unitstart := int64(-1)
-	headerstart := int64(-1)
-	headerend := int64(-1)
-
-	newattr(unit.DWInfo, dwarf.DW_AT_stmt_list, dwarf.DW_CLS_PTR, ls.Size, ls)
-
-	// Write .debug_line Line Number Program Header (sec 6.2.4)
-	// Fields marked with (*) must be changed for 64-bit dwarf
-	unitLengthOffset := ls.Size
-	createUnitLength(ctxt, ls, 0) // unit_length (*), filled in at end
-	unitstart = ls.Size
-	ls.AddUint16(ctxt.Arch, 2) // dwarf version (appendix F) -- version 3 is incompatible w/ XCode 9.0's dsymutil, latest supported on OSX 10.12 as of 2018-05
-	headerLengthOffset := ls.Size
-	addDwarfAddrField(ctxt, ls, 0) // header_length (*), filled in at end
-	headerstart = ls.Size
-
-	// cpos == unitstart + 4 + 2 + 4
-	ls.AddUint8(1)                // minimum_instruction_length
-	ls.AddUint8(is_stmt)          // default_is_stmt
-	ls.AddUint8(LINE_BASE & 0xFF) // line_base
-	ls.AddUint8(LINE_RANGE)       // line_range
-	ls.AddUint8(OPCODE_BASE)      // opcode_base
-	ls.AddUint8(0)                // standard_opcode_lengths[1]
-	ls.AddUint8(1)                // standard_opcode_lengths[2]
-	ls.AddUint8(1)                // standard_opcode_lengths[3]
-	ls.AddUint8(1)                // standard_opcode_lengths[4]
-	ls.AddUint8(1)                // standard_opcode_lengths[5]
-	ls.AddUint8(0)                // standard_opcode_lengths[6]
-	ls.AddUint8(0)                // standard_opcode_lengths[7]
-	ls.AddUint8(0)                // standard_opcode_lengths[8]
-	ls.AddUint8(1)                // standard_opcode_lengths[9]
-	ls.AddUint8(0)                // standard_opcode_lengths[10]
-	ls.AddUint8(0)                // include_directories  (empty)
-
-	// Copy over the file table.
-	fileNums := make(map[string]int)
-	for i, name := range unit.DWARFFileTable {
-		if len(name) != 0 {
-			if strings.HasPrefix(name, src.FileSymPrefix) {
-				name = name[len(src.FileSymPrefix):]
-			}
-			name = expandGoroot(name)
-		} else {
-			// Can't have empty filenames, and having a unique filename is quite useful
-			// for debugging.
-			name = fmt.Sprintf("<missing>_%d", i)
-		}
-		fileNums[name] = i + 1
-		dwarfctxt.AddString(ls, name)
-		ls.AddUint8(0)
-		ls.AddUint8(0)
-		ls.AddUint8(0)
-	}
-	// Grab files for inlined functions.
-	// TODO: With difficulty, this could be moved into the compiler.
-	for _, s := range unit.Textp {
-		dsym := dwarfFuncSym(ctxt, s, dwarf.InfoPrefix, true)
-		for ri := 0; ri < len(dsym.R); ri++ {
-			r := &dsym.R[ri]
-			if r.Type != objabi.R_DWARFFILEREF {
-				continue
-			}
-			name := r.Sym.Name
-			if _, ok := fileNums[name]; ok {
-				continue
-			}
-			fileNums[name] = len(fileNums) + 1
-			dwarfctxt.AddString(ls, name)
-			ls.AddUint8(0)
-			ls.AddUint8(0)
-			ls.AddUint8(0)
-		}
-	}
-
-	// 4 zeros: the string termination + 3 fields.
-	ls.AddUint8(0)
-	// terminate file_names.
-	headerend = ls.Size
-
-	// Output the state machine for each function remaining.
-	var lastAddr int64
-	for _, s := range unit.Textp {
-		finddebugruntimepath(s)
-
-		// Set the PC.
-		ls.AddUint8(0)
-		dwarf.Uleb128put(dwarfctxt, ls, 1+int64(ctxt.Arch.PtrSize))
-		ls.AddUint8(dwarf.DW_LNE_set_address)
-		addr := ls.AddAddr(ctxt.Arch, s)
-		// Make sure the units are sorted.
-		if addr < lastAddr {
-			Errorf(s, "address wasn't increasing %x < %x", addr, lastAddr)
-		}
-		lastAddr = addr
-
-		// Output the line table.
-		// TODO: Now that we have all the debug information in separate
-		// symbols, it would make sense to use a rope, and concatenate them all
-		// together rather then the append() below. This would allow us to have
-		// the compiler emit the DW_LNE_set_address and a rope data structure
-		// to concat them all together in the output.
-		lines := dwarfFuncSym(ctxt, s, dwarf.DebugLinesPrefix, false)
-		if lines != nil {
-			ls.P = append(ls.P, lines.P...)
-		}
-	}
-
-	ls.AddUint8(0) // start extended opcode
-	dwarf.Uleb128put(dwarfctxt, ls, 1)
-	ls.AddUint8(dwarf.DW_LNE_end_sequence)
-
-	if ctxt.HeadType == objabi.Haix {
-		saveDwsectCUSize(".debug_line", unit.Lib.Pkg, uint64(ls.Size-unitLengthOffset))
-	}
-	if isDwarf64(ctxt) {
-		ls.SetUint(ctxt.Arch, unitLengthOffset+4, uint64(ls.Size-unitstart)) // +4 because of 0xFFFFFFFF
-		ls.SetUint(ctxt.Arch, headerLengthOffset, uint64(headerend-headerstart))
-	} else {
-		ls.SetUint32(ctxt.Arch, unitLengthOffset, uint32(ls.Size-unitstart))
-		ls.SetUint32(ctxt.Arch, headerLengthOffset, uint32(headerend-headerstart))
-	}
-
-	// Process any R_DWARFFILEREF relocations, since we now know the
-	// line table file indices for this compilation unit. Note that
-	// this loop visits only subprogram DIEs: if the compiler is
-	// changed to generate DW_AT_decl_file attributes for other
-	// DIE flavors (ex: variables) then those DIEs would need to
-	// be included below.
-	missing := make(map[int]interface{})
-	s := unit.Textp[0]
-	for _, f := range unit.FuncDIEs {
-		for ri := range f.R {
-			r := &f.R[ri]
-			if r.Type != objabi.R_DWARFFILEREF {
-				continue
-			}
-			idx, ok := fileNums[r.Sym.Name]
-			if ok {
-				if int(int32(idx)) != idx {
-					Errorf(f, "bad R_DWARFFILEREF relocation: file index overflow")
-				}
-				if r.Siz != 4 {
-					Errorf(f, "bad R_DWARFFILEREF relocation: has size %d, expected 4", r.Siz)
-				}
-				if r.Off < 0 || r.Off+4 > int32(len(f.P)) {
-					Errorf(f, "bad R_DWARFFILEREF relocation offset %d + 4 would write past length %d", r.Off, len(s.P))
-					continue
-				}
-				if r.Add != 0 {
-					Errorf(f, "bad R_DWARFFILEREF relocation: addend not zero")
-				}
-				r.Sym.Attr |= sym.AttrReachable | sym.AttrNotInSymbolTable
-				r.Add = int64(idx) // record the index in r.Add, we'll apply it in the reloc phase.
-			} else {
-				_, found := missing[int(r.Sym.Value)]
-				if !found {
-					Errorf(f, "R_DWARFFILEREF relocation file missing: %v idx %d", r.Sym, r.Sym.Value)
-					missing[int(r.Sym.Value)] = nil
-				}
-			}
-		}
-	}
-}
-
-// writepcranges generates the DW_AT_ranges table for compilation unit cu.
-func writepcranges(ctxt *Link, unit *sym.CompilationUnit, base *sym.Symbol, pcs []dwarf.Range, ranges *sym.Symbol) {
-	var dwarfctxt dwarf.Context = dwctxt{ctxt}
-
-	unitLengthOffset := ranges.Size
-
-	// Create PC ranges for this CU.
-	newattr(unit.DWInfo, dwarf.DW_AT_ranges, dwarf.DW_CLS_PTR, ranges.Size, ranges)
-	newattr(unit.DWInfo, dwarf.DW_AT_low_pc, dwarf.DW_CLS_ADDRESS, base.Value, base)
-	dwarf.PutBasedRanges(dwarfctxt, ranges, pcs)
-
-	if ctxt.HeadType == objabi.Haix {
-		addDwsectCUSize(".debug_ranges", unit.Lib.Pkg, uint64(ranges.Size-unitLengthOffset))
-	}
-
-}
-
-/*
- *  Emit .debug_frame
- */
-const (
-	dataAlignmentFactor = -4
-)
-
-// appendPCDeltaCFA appends per-PC CFA deltas to b and returns the final slice.
-func appendPCDeltaCFA(arch *sys.Arch, b []byte, deltapc, cfa int64) []byte {
-	b = append(b, dwarf.DW_CFA_def_cfa_offset_sf)
-	b = dwarf.AppendSleb128(b, cfa/dataAlignmentFactor)
-
-	switch {
-	case deltapc < 0x40:
-		b = append(b, uint8(dwarf.DW_CFA_advance_loc+deltapc))
-	case deltapc < 0x100:
-		b = append(b, dwarf.DW_CFA_advance_loc1)
-		b = append(b, uint8(deltapc))
-	case deltapc < 0x10000:
-		b = append(b, dwarf.DW_CFA_advance_loc2, 0, 0)
-		arch.ByteOrder.PutUint16(b[len(b)-2:], uint16(deltapc))
-	default:
-		b = append(b, dwarf.DW_CFA_advance_loc4, 0, 0, 0, 0)
-		arch.ByteOrder.PutUint32(b[len(b)-4:], uint32(deltapc))
-	}
-	return b
-}
-
-func writeframes(ctxt *Link, syms []*sym.Symbol) []*sym.Symbol {
-	var dwarfctxt dwarf.Context = dwctxt{ctxt}
-	fs := ctxt.Syms.Lookup(".debug_frame", 0)
-	fs.Type = sym.SDWARFSECT
-	syms = append(syms, fs)
-
-	// Length field is 4 bytes on Dwarf32 and 12 bytes on Dwarf64
-	lengthFieldSize := int64(4)
-	if isDwarf64(ctxt) {
-		lengthFieldSize += 8
-	}
-
-	// Emit the CIE, Section 6.4.1
-	cieReserve := uint32(16)
-	if haslinkregister(ctxt) {
-		cieReserve = 32
-	}
-	if isDwarf64(ctxt) {
-		cieReserve += 4 // 4 bytes added for cid
-	}
-	createUnitLength(ctxt, fs, uint64(cieReserve))             // initial length, must be multiple of thearch.ptrsize
-	addDwarfAddrField(ctxt, fs, ^uint64(0))                    // cid
-	fs.AddUint8(3)                                             // dwarf version (appendix F)
-	fs.AddUint8(0)                                             // augmentation ""
-	dwarf.Uleb128put(dwarfctxt, fs, 1)                         // code_alignment_factor
-	dwarf.Sleb128put(dwarfctxt, fs, dataAlignmentFactor)       // all CFI offset calculations include multiplication with this factor
-	dwarf.Uleb128put(dwarfctxt, fs, int64(thearch.Dwarfreglr)) // return_address_register
-
-	fs.AddUint8(dwarf.DW_CFA_def_cfa)                          // Set the current frame address..
-	dwarf.Uleb128put(dwarfctxt, fs, int64(thearch.Dwarfregsp)) // ...to use the value in the platform's SP register (defined in l.go)...
-	if haslinkregister(ctxt) {
-		dwarf.Uleb128put(dwarfctxt, fs, int64(0)) // ...plus a 0 offset.
-
-		fs.AddUint8(dwarf.DW_CFA_same_value) // The platform's link register is unchanged during the prologue.
-		dwarf.Uleb128put(dwarfctxt, fs, int64(thearch.Dwarfreglr))
-
-		fs.AddUint8(dwarf.DW_CFA_val_offset)                       // The previous value...
-		dwarf.Uleb128put(dwarfctxt, fs, int64(thearch.Dwarfregsp)) // ...of the platform's SP register...
-		dwarf.Uleb128put(dwarfctxt, fs, int64(0))                  // ...is CFA+0.
-	} else {
-		dwarf.Uleb128put(dwarfctxt, fs, int64(ctxt.Arch.PtrSize)) // ...plus the word size (because the call instruction implicitly adds one word to the frame).
-
-		fs.AddUint8(dwarf.DW_CFA_offset_extended)                                      // The previous value...
-		dwarf.Uleb128put(dwarfctxt, fs, int64(thearch.Dwarfreglr))                     // ...of the return address...
-		dwarf.Uleb128put(dwarfctxt, fs, int64(-ctxt.Arch.PtrSize)/dataAlignmentFactor) // ...is saved at [CFA - (PtrSize/4)].
-	}
-
-	pad := int64(cieReserve) + lengthFieldSize - fs.Size
-
-	if pad < 0 {
-		Exitf("dwarf: cieReserve too small by %d bytes.", -pad)
-	}
-
-	fs.AddBytes(zeros[:pad])
-
-	var deltaBuf []byte
-	pcsp := obj.NewPCIter(uint32(ctxt.Arch.MinLC))
-	for _, s := range ctxt.Textp {
-		if s.FuncInfo == nil {
-			continue
-		}
-
-		// Emit a FDE, Section 6.4.1.
-		// First build the section contents into a byte buffer.
-		deltaBuf = deltaBuf[:0]
-		if haslinkregister(ctxt) && s.Attr.TopFrame() {
-			// Mark the link register as having an undefined value.
-			// This stops call stack unwinders progressing any further.
-			// TODO: similar mark on non-LR architectures.
-			deltaBuf = append(deltaBuf, dwarf.DW_CFA_undefined)
-			deltaBuf = dwarf.AppendUleb128(deltaBuf, uint64(thearch.Dwarfreglr))
-		}
-		for pcsp.Init(s.FuncInfo.Pcsp.P); !pcsp.Done; pcsp.Next() {
-			nextpc := pcsp.NextPC
-
-			// pciterinit goes up to the end of the function,
-			// but DWARF expects us to stop just before the end.
-			if int64(nextpc) == s.Size {
-				nextpc--
-				if nextpc < pcsp.PC {
-					continue
-				}
-			}
-
-			spdelta := int64(pcsp.Value)
-			if !haslinkregister(ctxt) {
-				// Return address has been pushed onto stack.
-				spdelta += int64(ctxt.Arch.PtrSize)
-			}
-
-			if haslinkregister(ctxt) && !s.Attr.TopFrame() {
-				// TODO(bryanpkc): This is imprecise. In general, the instruction
-				// that stores the return address to the stack frame is not the
-				// same one that allocates the frame.
-				if pcsp.Value > 0 {
-					// The return address is preserved at (CFA-frame_size)
-					// after a stack frame has been allocated.
-					deltaBuf = append(deltaBuf, dwarf.DW_CFA_offset_extended_sf)
-					deltaBuf = dwarf.AppendUleb128(deltaBuf, uint64(thearch.Dwarfreglr))
-					deltaBuf = dwarf.AppendSleb128(deltaBuf, -spdelta/dataAlignmentFactor)
-				} else {
-					// The return address is restored into the link register
-					// when a stack frame has been de-allocated.
-					deltaBuf = append(deltaBuf, dwarf.DW_CFA_same_value)
-					deltaBuf = dwarf.AppendUleb128(deltaBuf, uint64(thearch.Dwarfreglr))
-				}
-			}
-
-			deltaBuf = appendPCDeltaCFA(ctxt.Arch, deltaBuf, int64(nextpc)-int64(pcsp.PC), spdelta)
-		}
-		pad := int(Rnd(int64(len(deltaBuf)), int64(ctxt.Arch.PtrSize))) - len(deltaBuf)
-		deltaBuf = append(deltaBuf, zeros[:pad]...)
-
-		// Emit the FDE header, Section 6.4.1.
-		//	4 bytes: length, must be multiple of thearch.ptrsize
-		//	4/8 bytes: Pointer to the CIE above, at offset 0
-		//	ptrsize: initial location
-		//	ptrsize: address range
-
-		fdeLength := uint64(4 + 2*ctxt.Arch.PtrSize + len(deltaBuf))
-		if isDwarf64(ctxt) {
-			fdeLength += 4 // 4 bytes added for CIE pointer
-		}
-		createUnitLength(ctxt, fs, fdeLength)
-
-		if ctxt.LinkMode == LinkExternal {
-			addDwarfAddrRef(ctxt, fs, fs)
-		} else {
-			addDwarfAddrField(ctxt, fs, 0) // CIE offset
-		}
-		fs.AddAddr(ctxt.Arch, s)
-		fs.AddUintXX(ctxt.Arch, uint64(s.Size), ctxt.Arch.PtrSize) // address range
-		fs.AddBytes(deltaBuf)
-
-		if ctxt.HeadType == objabi.Haix {
-			addDwsectCUSize(".debug_frame", s.File, fdeLength+uint64(lengthFieldSize))
-		}
-	}
-	return syms
-}
-
-/*
- *  Walk DWarfDebugInfoEntries, and emit .debug_info
- */
-const (
-	COMPUNITHEADERSIZE = 4 + 2 + 4 + 1
-)
-
-func writeinfo(ctxt *Link, syms []*sym.Symbol, units []*sym.CompilationUnit, abbrevsym *sym.Symbol, pubNames, pubTypes *pubWriter) []*sym.Symbol {
-	infosec := ctxt.Syms.Lookup(".debug_info", 0)
-	infosec.Type = sym.SDWARFINFO
-	infosec.Attr |= sym.AttrReachable
-	syms = append(syms, infosec)
-
-	var dwarfctxt dwarf.Context = dwctxt{ctxt}
-
-	for _, u := range units {
-		compunit := u.DWInfo
-		s := dtolsym(compunit.Sym)
-
-		if len(u.Textp) == 0 && u.DWInfo.Child == nil {
-			continue
-		}
-
-		pubNames.beginCompUnit(compunit)
-		pubTypes.beginCompUnit(compunit)
-
-		// Write .debug_info Compilation Unit Header (sec 7.5.1)
-		// Fields marked with (*) must be changed for 64-bit dwarf
-		// This must match COMPUNITHEADERSIZE above.
-		createUnitLength(ctxt, s, 0) // unit_length (*), will be filled in later.
-		s.AddUint16(ctxt.Arch, 4)    // dwarf version (appendix F)
-
-		// debug_abbrev_offset (*)
-		addDwarfAddrRef(ctxt, s, abbrevsym)
-
-		s.AddUint8(uint8(ctxt.Arch.PtrSize)) // address_size
-
-		dwarf.Uleb128put(dwarfctxt, s, int64(compunit.Abbrev))
-		dwarf.PutAttrs(dwarfctxt, s, compunit.Abbrev, compunit.Attr)
-
-		cu := []*sym.Symbol{s}
-		cu = append(cu, u.AbsFnDIEs...)
-		cu = append(cu, u.FuncDIEs...)
-		if u.Consts != nil {
-			cu = append(cu, u.Consts)
-		}
-		var cusize int64
-		for _, child := range cu {
-			cusize += child.Size
-		}
-
-		for die := compunit.Child; die != nil; die = die.Link {
-			l := len(cu)
-			lastSymSz := cu[l-1].Size
-			cu = putdie(ctxt, dwarfctxt, cu, die)
-			if ispubname(die) {
-				pubNames.add(die, cusize)
-			}
-			if ispubtype(die) {
-				pubTypes.add(die, cusize)
-			}
-			if lastSymSz != cu[l-1].Size {
-				// putdie will sometimes append directly to the last symbol of the list
-				cusize = cusize - lastSymSz + cu[l-1].Size
-			}
-			for _, child := range cu[l:] {
-				cusize += child.Size
-			}
-		}
-		cu[len(cu)-1].AddUint8(0) // closes compilation unit DIE
-		cusize++
-
-		// Save size for AIX symbol table.
-		if ctxt.HeadType == objabi.Haix {
-			saveDwsectCUSize(".debug_info", getPkgFromCUSym(s), uint64(cusize))
-		}
-		if isDwarf64(ctxt) {
-			cusize -= 12                            // exclude the length field.
-			s.SetUint(ctxt.Arch, 4, uint64(cusize)) // 4 because of 0XFFFFFFFF
-		} else {
-			cusize -= 4 // exclude the length field.
-			s.SetUint32(ctxt.Arch, 0, uint32(cusize))
-		}
-		pubNames.endCompUnit(compunit, uint32(cusize)+4)
-		pubTypes.endCompUnit(compunit, uint32(cusize)+4)
-		syms = append(syms, cu...)
-	}
-	return syms
-}
-
-/*
- *  Emit .debug_pubnames/_types.  _info must have been written before,
- *  because we need die->offs and infoo/infosize;
- */
-func ispubname(die *dwarf.DWDie) bool {
-	switch die.Abbrev {
-	case dwarf.DW_ABRV_FUNCTION, dwarf.DW_ABRV_VARIABLE:
-		a := getattr(die, dwarf.DW_AT_external)
-		return a != nil && a.Value != 0
-	}
-
-	return false
-}
-
-func ispubtype(die *dwarf.DWDie) bool {
-	return die.Abbrev >= dwarf.DW_ABRV_NULLTYPE
-}
-
-type pubWriter struct {
-	ctxt  *Link
-	s     *sym.Symbol
-	sname string
-
-	sectionstart int64
-	culengthOff  int64
-}
-
-func newPubWriter(ctxt *Link, sname string) *pubWriter {
-	s := ctxt.Syms.Lookup(sname, 0)
-	s.Type = sym.SDWARFSECT
-	return &pubWriter{ctxt: ctxt, s: s, sname: sname}
-}
-
-func (pw *pubWriter) beginCompUnit(compunit *dwarf.DWDie) {
-	pw.sectionstart = pw.s.Size
-
-	// Write .debug_pubnames/types	Header (sec 6.1.1)
-	createUnitLength(pw.ctxt, pw.s, 0)                    // unit_length (*), will be filled in later.
-	pw.s.AddUint16(pw.ctxt.Arch, 2)                       // dwarf version (appendix F)
-	addDwarfAddrRef(pw.ctxt, pw.s, dtolsym(compunit.Sym)) // debug_info_offset (of the Comp unit Header)
-	pw.culengthOff = pw.s.Size
-	addDwarfAddrField(pw.ctxt, pw.s, uint64(0)) // debug_info_length, will be filled in later.
-
-}
-
-func (pw *pubWriter) add(die *dwarf.DWDie, offset int64) {
-	dwa := getattr(die, dwarf.DW_AT_name)
-	name := dwa.Data.(string)
-	if die.Sym == nil {
-		fmt.Println("Missing sym for ", name)
-	}
-	addDwarfAddrField(pw.ctxt, pw.s, uint64(offset))
-	Addstring(pw.s, name)
-}
-
-func (pw *pubWriter) endCompUnit(compunit *dwarf.DWDie, culength uint32) {
-	addDwarfAddrField(pw.ctxt, pw.s, 0) // Null offset
-
-	// On AIX, save the current size of this compilation unit.
-	if pw.ctxt.HeadType == objabi.Haix {
-		saveDwsectCUSize(pw.sname, getPkgFromCUSym(dtolsym(compunit.Sym)), uint64(pw.s.Size-pw.sectionstart))
-	}
-	if isDwarf64(pw.ctxt) {
-		pw.s.SetUint(pw.ctxt.Arch, pw.sectionstart+4, uint64(pw.s.Size-pw.sectionstart)-12) // exclude the length field.
-		pw.s.SetUint(pw.ctxt.Arch, pw.culengthOff, uint64(culength))
-	} else {
-		pw.s.SetUint32(pw.ctxt.Arch, pw.sectionstart, uint32(pw.s.Size-pw.sectionstart)-4) // exclude the length field.
-		pw.s.SetUint32(pw.ctxt.Arch, pw.culengthOff, culength)
-	}
-}
-
-func writegdbscript(ctxt *Link, syms []*sym.Symbol) []*sym.Symbol {
-	// TODO (aix): make it available
-	if ctxt.HeadType == objabi.Haix {
-		return syms
-	}
-	if ctxt.LinkMode == LinkExternal && ctxt.HeadType == objabi.Hwindows && ctxt.BuildMode == BuildModeCArchive {
-		// gcc on Windows places .debug_gdb_scripts in the wrong location, which
-		// causes the program not to run. See https://golang.org/issue/20183
-		// Non c-archives can avoid this issue via a linker script
-		// (see fix near writeGDBLinkerScript).
-		// c-archive users would need to specify the linker script manually.
-		// For UX it's better not to deal with this.
-		return syms
-	}
-
-	if gdbscript != "" {
-		s := ctxt.Syms.Lookup(".debug_gdb_scripts", 0)
-		s.Type = sym.SDWARFSECT
-		syms = append(syms, s)
-		s.AddUint8(1) // magic 1 byte?
-		Addstring(s, gdbscript)
-	}
-
-	return syms
-}
-
-var prototypedies map[string]*dwarf.DWDie
-
-func dwarfEnabled(ctxt *Link) bool {
-	if *FlagW { // disable dwarf
-		return false
-	}
-	if *FlagS && ctxt.HeadType != objabi.Hdarwin {
-		return false
-	}
-	if ctxt.HeadType == objabi.Hplan9 || ctxt.HeadType == objabi.Hjs {
-		return false
-	}
-
-	if ctxt.LinkMode == LinkExternal {
-		switch {
-		case ctxt.IsELF:
-		case ctxt.HeadType == objabi.Hdarwin:
-		case ctxt.HeadType == objabi.Hwindows:
-		case ctxt.HeadType == objabi.Haix:
-			res, err := dwarf.IsDWARFEnabledOnAIXLd(ctxt.extld())
-			if err != nil {
-				Exitf("%v", err)
-			}
-			return res
-		default:
-			return false
-		}
-	}
-
-	return true
-}
-
-// dwarfGenerateDebugInfo generated debug info entries for all types,
-// variables and functions in the program.
-// Along with dwarfGenerateDebugSyms they are the two main entry points into
-// dwarf generation: dwarfGenerateDebugInfo does all the work that should be
-// done before symbol names are mangled while dwarfgeneratedebugsyms does
-// all the work that can only be done after addresses have been assigned to
-// text symbols.
-func dwarfGenerateDebugInfo(ctxt *Link) {
-	if !dwarfEnabled(ctxt) {
-		return
-	}
-
-	if ctxt.HeadType == objabi.Haix {
-		// Initial map used to store package size for each DWARF section.
-		dwsectCUSize = make(map[string]uint64)
-	}
-
-	// Forctxt.Diagnostic messages.
-	newattr(&dwtypes, dwarf.DW_AT_name, dwarf.DW_CLS_STRING, int64(len("dwtypes")), "dwtypes")
-
-	// Some types that must exist to define other ones.
-	newdie(ctxt, &dwtypes, dwarf.DW_ABRV_NULLTYPE, "<unspecified>", 0)
-
-	newdie(ctxt, &dwtypes, dwarf.DW_ABRV_NULLTYPE, "void", 0)
-	newdie(ctxt, &dwtypes, dwarf.DW_ABRV_BARE_PTRTYPE, "unsafe.Pointer", 0)
-
-	die := newdie(ctxt, &dwtypes, dwarf.DW_ABRV_BASETYPE, "uintptr", 0) // needed for array size
-	newattr(die, dwarf.DW_AT_encoding, dwarf.DW_CLS_CONSTANT, dwarf.DW_ATE_unsigned, 0)
-	newattr(die, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, int64(ctxt.Arch.PtrSize), 0)
-	newattr(die, dwarf.DW_AT_go_kind, dwarf.DW_CLS_CONSTANT, objabi.KindUintptr, 0)
-	newattr(die, dwarf.DW_AT_go_runtime_type, dwarf.DW_CLS_ADDRESS, 0, lookupOrDiag(ctxt, "type.uintptr"))
-
-	// Prototypes needed for type synthesis.
-	prototypedies = map[string]*dwarf.DWDie{
-		"type.runtime.stringStructDWARF": nil,
-		"type.runtime.slice":             nil,
-		"type.runtime.hmap":              nil,
-		"type.runtime.bmap":              nil,
-		"type.runtime.sudog":             nil,
-		"type.runtime.waitq":             nil,
-		"type.runtime.hchan":             nil,
-	}
-
-	// Needed by the prettyprinter code for interface inspection.
-	for _, typ := range []string{
-		"type.runtime._type",
-		"type.runtime.arraytype",
-		"type.runtime.chantype",
-		"type.runtime.functype",
-		"type.runtime.maptype",
-		"type.runtime.ptrtype",
-		"type.runtime.slicetype",
-		"type.runtime.structtype",
-		"type.runtime.interfacetype",
-		"type.runtime.itab",
-		"type.runtime.imethod"} {
-		defgotype(ctxt, lookupOrDiag(ctxt, typ))
-	}
-
-	// fake root DIE for compile unit DIEs
-	var dwroot dwarf.DWDie
-	flagVariants := make(map[string]bool)
-
-	for _, lib := range ctxt.Library {
-		consts := ctxt.Syms.ROLookup(dwarf.ConstInfoPrefix+lib.Pkg, 0)
-		for _, unit := range lib.Units {
-			// We drop the constants into the first CU.
-			if consts != nil {
-				importInfoSymbol(ctxt, consts)
-				unit.Consts = consts
-				consts = nil
-			}
-
-			ctxt.compUnits = append(ctxt.compUnits, unit)
-
-			// We need at least one runtime unit.
-			if unit.Lib.Pkg == "runtime" {
-				ctxt.runtimeCU = unit
-			}
-
-			unit.DWInfo = newdie(ctxt, &dwroot, dwarf.DW_ABRV_COMPUNIT, unit.Lib.Pkg, 0)
-			newattr(unit.DWInfo, dwarf.DW_AT_language, dwarf.DW_CLS_CONSTANT, int64(dwarf.DW_LANG_Go), 0)
-			// OS X linker requires compilation dir or absolute path in comp unit name to output debug info.
-			compDir := getCompilationDir()
-			// TODO: Make this be the actual compilation directory, not
-			// the linker directory. If we move CU construction into the
-			// compiler, this should happen naturally.
-			newattr(unit.DWInfo, dwarf.DW_AT_comp_dir, dwarf.DW_CLS_STRING, int64(len(compDir)), compDir)
-			producerExtra := ctxt.Syms.Lookup(dwarf.CUInfoPrefix+"producer."+unit.Lib.Pkg, 0)
-			producer := "Go cmd/compile " + objabi.Version
-			if len(producerExtra.P) > 0 {
-				// We put a semicolon before the flags to clearly
-				// separate them from the version, which can be long
-				// and have lots of weird things in it in development
-				// versions. We promise not to put a semicolon in the
-				// version, so it should be safe for readers to scan
-				// forward to the semicolon.
-				producer += "; " + string(producerExtra.P)
-				flagVariants[string(producerExtra.P)] = true
-			} else {
-				flagVariants[""] = true
-			}
-
-			newattr(unit.DWInfo, dwarf.DW_AT_producer, dwarf.DW_CLS_STRING, int64(len(producer)), producer)
-
-			var pkgname string
-			if s := ctxt.Syms.ROLookup(dwarf.CUInfoPrefix+"packagename."+unit.Lib.Pkg, 0); s != nil {
-				pkgname = string(s.P)
-			}
-			newattr(unit.DWInfo, dwarf.DW_AT_go_package_name, dwarf.DW_CLS_STRING, int64(len(pkgname)), pkgname)
-
-			if len(unit.Textp) == 0 {
-				unit.DWInfo.Abbrev = dwarf.DW_ABRV_COMPUNIT_TEXTLESS
-			}
-
-			// Scan all functions in this compilation unit, create DIEs for all
-			// referenced types, create the file table for debug_line, find all
-			// referenced abstract functions.
-			// Collect all debug_range symbols in unit.rangeSyms
-			for _, s := range unit.Textp { // textp has been dead-code-eliminated already.
-				dsym := dwarfFuncSym(ctxt, s, dwarf.InfoPrefix, false)
-				dsym.Attr |= sym.AttrNotInSymbolTable | sym.AttrReachable
-				dsym.Type = sym.SDWARFINFO
-				unit.FuncDIEs = append(unit.FuncDIEs, dsym)
-
-				rangeSym := dwarfFuncSym(ctxt, s, dwarf.RangePrefix, false)
-				if rangeSym != nil && rangeSym.Size > 0 {
-					rangeSym.Attr |= sym.AttrReachable | sym.AttrNotInSymbolTable
-					rangeSym.Type = sym.SDWARFRANGE
-					if ctxt.HeadType == objabi.Haix {
-						addDwsectCUSize(".debug_ranges", unit.Lib.Pkg, uint64(rangeSym.Size))
-					}
-					unit.RangeSyms = append(unit.RangeSyms, rangeSym)
-				}
-
-				for ri := 0; ri < len(dsym.R); ri++ {
-					r := &dsym.R[ri]
-					if r.Type == objabi.R_DWARFSECREF {
-						rsym := r.Sym
-						if strings.HasPrefix(rsym.Name, dwarf.InfoPrefix) && strings.HasSuffix(rsym.Name, dwarf.AbstractFuncSuffix) && !rsym.Attr.OnList() {
-							// abstract function
-							rsym.Attr |= sym.AttrOnList
-							unit.AbsFnDIEs = append(unit.AbsFnDIEs, rsym)
-							importInfoSymbol(ctxt, rsym)
-						} else if rsym.Size == 0 {
-							// a type we do not have a DIE for
-							n := nameFromDIESym(rsym)
-							defgotype(ctxt, ctxt.Syms.Lookup("type."+n, 0))
-						}
-					}
-				}
-			}
-		}
-	}
-
-	// Fix for 31034: if the objects feeding into this link were compiled
-	// with different sets of flags, then don't issue an error if
-	// the -strictdups checks fail.
-	if checkStrictDups > 1 && len(flagVariants) > 1 {
-		checkStrictDups = 1
-	}
-
-	// Create DIEs for global variables and the types they use.
-	genasmsym(ctxt, defdwsymb)
-
-	// Create DIEs for variable types indirectly referenced by function
-	// autos (which may not appear directly as param/var DIEs).
-	for _, lib := range ctxt.Library {
-		for _, unit := range lib.Units {
-			lists := [][]*sym.Symbol{unit.AbsFnDIEs, unit.FuncDIEs}
-			for _, list := range lists {
-				for _, s := range list {
-					for i := 0; i < len(s.R); i++ {
-						r := &s.R[i]
-						if r.Type == objabi.R_USETYPE {
-							defgotype(ctxt, r.Sym)
-						}
-					}
-				}
-			}
-		}
-	}
-
-	synthesizestringtypes(ctxt, dwtypes.Child)
-	synthesizeslicetypes(ctxt, dwtypes.Child)
-	synthesizemaptypes(ctxt, dwtypes.Child)
-	synthesizechantypes(ctxt, dwtypes.Child)
-}
-
-// dwarfGenerateDebugSyms constructs debug_line, debug_frame, debug_loc,
-// debug_pubnames and debug_pubtypes. It also writes out the debug_info
-// section using symbols generated in dwarfGenerateDebugInfo.
-func dwarfGenerateDebugSyms(ctxt *Link) {
-	if !dwarfEnabled(ctxt) {
-		return
-	}
-
-	abbrev := writeabbrev(ctxt)
-	syms := []*sym.Symbol{abbrev}
-
-	calcCompUnitRanges(ctxt)
-	sort.Sort(compilationUnitByStartPC(ctxt.compUnits))
-
-	// Write per-package line and range tables and start their CU DIEs.
-	debugLine := ctxt.Syms.Lookup(".debug_line", 0)
-	debugLine.Type = sym.SDWARFSECT
-	debugRanges := ctxt.Syms.Lookup(".debug_ranges", 0)
-	debugRanges.Type = sym.SDWARFRANGE
-	debugRanges.Attr |= sym.AttrReachable
-	syms = append(syms, debugLine)
-	for _, u := range ctxt.compUnits {
-		reversetree(&u.DWInfo.Child)
-		if u.DWInfo.Abbrev == dwarf.DW_ABRV_COMPUNIT_TEXTLESS {
-			continue
-		}
-		writelines(ctxt, u, debugLine)
-		writepcranges(ctxt, u, u.Textp[0], u.PCs, debugRanges)
-	}
-
-	// newdie adds DIEs to the *beginning* of the parent's DIE list.
-	// Now that we're done creating DIEs, reverse the trees so DIEs
-	// appear in the order they were created.
-	reversetree(&dwtypes.Child)
-	movetomodule(ctxt, &dwtypes)
-
-	pubNames := newPubWriter(ctxt, ".debug_pubnames")
-	pubTypes := newPubWriter(ctxt, ".debug_pubtypes")
-
-	// Need to reorder symbols so sym.SDWARFINFO is after all sym.SDWARFSECT
-	infosyms := writeinfo(ctxt, nil, ctxt.compUnits, abbrev, pubNames, pubTypes)
-
-	syms = writeframes(ctxt, syms)
-	syms = append(syms, pubNames.s, pubTypes.s)
-	syms = writegdbscript(ctxt, syms)
-	// Now we're done writing SDWARFSECT symbols, so we can write
-	// other SDWARF* symbols.
-	syms = append(syms, infosyms...)
-	syms = collectlocs(ctxt, syms, ctxt.compUnits)
-	syms = append(syms, debugRanges)
-	for _, unit := range ctxt.compUnits {
-		syms = append(syms, unit.RangeSyms...)
-	}
-	dwarfp = syms
-}
-
-func collectlocs(ctxt *Link, syms []*sym.Symbol, units []*sym.CompilationUnit) []*sym.Symbol {
-	empty := true
-	for _, u := range units {
-		for _, fn := range u.FuncDIEs {
-			for i := range fn.R {
-				reloc := &fn.R[i] // Copying sym.Reloc has measurable impact on performance
-				if reloc.Type == objabi.R_DWARFSECREF && strings.HasPrefix(reloc.Sym.Name, dwarf.LocPrefix) {
-					reloc.Sym.Attr |= sym.AttrReachable | sym.AttrNotInSymbolTable
-					syms = append(syms, reloc.Sym)
-					empty = false
-					// One location list entry per function, but many relocations to it. Don't duplicate.
-					break
-				}
-			}
-		}
-	}
-	// Don't emit .debug_loc if it's empty -- it makes the ARM linker mad.
-	if !empty {
-		locsym := ctxt.Syms.Lookup(".debug_loc", 0)
-		locsym.Type = sym.SDWARFLOC
-		locsym.Attr |= sym.AttrReachable
-		syms = append(syms, locsym)
-	}
-	return syms
-}
-
-// Read a pointer-sized uint from the beginning of buf.
-func readPtr(ctxt *Link, buf []byte) uint64 {
-	switch ctxt.Arch.PtrSize {
-	case 4:
-		return uint64(ctxt.Arch.ByteOrder.Uint32(buf))
-	case 8:
-		return ctxt.Arch.ByteOrder.Uint64(buf)
-	default:
-		panic("unexpected pointer size")
-	}
-}
-
-/*
- *  Elf.
- */
-func dwarfaddshstrings(ctxt *Link, shstrtab *sym.Symbol) {
-	if *FlagW { // disable dwarf
-		return
-	}
-
-	secs := []string{"abbrev", "frame", "info", "loc", "line", "pubnames", "pubtypes", "gdb_scripts", "ranges"}
-	for _, sec := range secs {
-		Addstring(shstrtab, ".debug_"+sec)
-		if ctxt.LinkMode == LinkExternal {
-			Addstring(shstrtab, elfRelType+".debug_"+sec)
-		} else {
-			Addstring(shstrtab, ".zdebug_"+sec)
-		}
-	}
-}
-
-// Add section symbols for DWARF debug info.  This is called before
-// dwarfaddelfheaders.
-func dwarfaddelfsectionsyms(ctxt *Link) {
-	if *FlagW { // disable dwarf
-		return
-	}
-	if ctxt.LinkMode != LinkExternal {
-		return
-	}
-
-	s := ctxt.Syms.Lookup(".debug_info", 0)
-	putelfsectionsym(ctxt.Out, s, s.Sect.Elfsect.(*ElfShdr).shnum)
-	s = ctxt.Syms.Lookup(".debug_abbrev", 0)
-	putelfsectionsym(ctxt.Out, s, s.Sect.Elfsect.(*ElfShdr).shnum)
-	s = ctxt.Syms.Lookup(".debug_line", 0)
-	putelfsectionsym(ctxt.Out, s, s.Sect.Elfsect.(*ElfShdr).shnum)
-	s = ctxt.Syms.Lookup(".debug_frame", 0)
-	putelfsectionsym(ctxt.Out, s, s.Sect.Elfsect.(*ElfShdr).shnum)
-	s = ctxt.Syms.Lookup(".debug_loc", 0)
-	if s.Sect != nil {
-		putelfsectionsym(ctxt.Out, s, s.Sect.Elfsect.(*ElfShdr).shnum)
-	}
-	s = ctxt.Syms.Lookup(".debug_ranges", 0)
-	if s.Sect != nil {
-		putelfsectionsym(ctxt.Out, s, s.Sect.Elfsect.(*ElfShdr).shnum)
-	}
-}
-
-// dwarfcompress compresses the DWARF sections. Relocations are applied
-// on the fly. After this, dwarfp will contain a different (new) set of
-// symbols, and sections may have been replaced.
-func dwarfcompress(ctxt *Link) {
-	supported := ctxt.IsELF || ctxt.HeadType == objabi.Hwindows || ctxt.HeadType == objabi.Hdarwin
-	if !ctxt.compressDWARF || !supported || ctxt.LinkMode != LinkInternal {
-		return
-	}
-
-	var start int
-	var newDwarfp []*sym.Symbol
-	Segdwarf.Sections = Segdwarf.Sections[:0]
-	for i, s := range dwarfp {
-		// Find the boundaries between sections and compress
-		// the whole section once we've found the last of its
-		// symbols.
-		if i+1 >= len(dwarfp) || s.Sect != dwarfp[i+1].Sect {
-			s1 := compressSyms(ctxt, dwarfp[start:i+1])
-			if s1 == nil {
-				// Compression didn't help.
-				newDwarfp = append(newDwarfp, dwarfp[start:i+1]...)
-				Segdwarf.Sections = append(Segdwarf.Sections, s.Sect)
-			} else {
-				compressedSegName := ".zdebug_" + s.Sect.Name[len(".debug_"):]
-				sect := addsection(ctxt.Arch, &Segdwarf, compressedSegName, 04)
-				sect.Length = uint64(len(s1))
-				newSym := ctxt.Syms.Lookup(compressedSegName, 0)
-				newSym.P = s1
-				newSym.Size = int64(len(s1))
-				newSym.Sect = sect
-				newDwarfp = append(newDwarfp, newSym)
-			}
-			start = i + 1
-		}
-	}
-	dwarfp = newDwarfp
-	ctxt.relocbuf = nil // no longer needed, don't hold it live
-
-	// 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 _, s := range dwarfp {
-		s.Value = int64(pos)
-		if s.Sect != prevSect {
-			s.Sect.Vaddr = uint64(s.Value)
-			prevSect = s.Sect
-		}
-		if s.Sub != nil {
-			log.Fatalf("%s: unexpected sub-symbols", s)
-		}
-		pos += uint64(s.Size)
-		if ctxt.HeadType == objabi.Hwindows {
-			pos = uint64(Rnd(int64(pos), PEFILEALIGN))
-		}
-
-	}
-	Segdwarf.Length = pos - Segdwarf.Vaddr
-}
-
-type compilationUnitByStartPC []*sym.CompilationUnit
-
-func (v compilationUnitByStartPC) Len() int      { return len(v) }
-func (v compilationUnitByStartPC) Swap(i, j int) { v[i], v[j] = v[j], v[i] }
-
-func (v compilationUnitByStartPC) Less(i, j int) bool {
-	switch {
-	case len(v[i].Textp) == 0 && len(v[j].Textp) == 0:
-		return v[i].Lib.Pkg < v[j].Lib.Pkg
-	case len(v[i].Textp) != 0 && len(v[j].Textp) == 0:
-		return true
-	case len(v[i].Textp) == 0 && len(v[j].Textp) != 0:
-		return false
-	default:
-		return v[i].Textp[0].Value < v[j].Textp[0].Value
-	}
-}
-
-// On AIX, the symbol table needs to know where are the compilation units parts
-// for a specific package in each .dw section.
-// dwsectCUSize map will save the size of a compilation unit for
-// the corresponding .dw section.
-// This size can later be retrieved with the index "sectionName.pkgName".
-var dwsectCUSize map[string]uint64
-
-// getDwsectCUSize retrieves the corresponding package size inside the current section.
-func getDwsectCUSize(sname string, pkgname string) uint64 {
-	return dwsectCUSize[sname+"."+pkgname]
-}
-
-func saveDwsectCUSize(sname string, pkgname string, size uint64) {
-	dwsectCUSize[sname+"."+pkgname] = size
-}
-
-func addDwsectCUSize(sname string, pkgname string, size uint64) {
-	dwsectCUSize[sname+"."+pkgname] += size
-}
-
-// getPkgFromCUSym returns the package name for the compilation unit
-// represented by s.
-// The prefix dwarf.InfoPrefix+".pkg." needs to be removed in order to get
-// the package name.
-func getPkgFromCUSym(s *sym.Symbol) string {
-	return strings.TrimPrefix(s.Name, dwarf.InfoPrefix+".pkg.")
-}
diff --git a/src/cmd/oldlink/internal/ld/elf.go b/src/cmd/oldlink/internal/ld/elf.go
deleted file mode 100644
index 28cab75..0000000
--- a/src/cmd/oldlink/internal/ld/elf.go
+++ /dev/null
@@ -1,2448 +0,0 @@
-// Copyright 2009 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/objabi"
-	"cmd/internal/sys"
-	"cmd/oldlink/internal/sym"
-	"crypto/sha1"
-	"encoding/binary"
-	"encoding/hex"
-	"io"
-	"path/filepath"
-	"sort"
-	"strings"
-)
-
-/*
- * Derived from:
- * $FreeBSD: src/sys/sys/elf32.h,v 1.8.14.1 2005/12/30 22:13:58 marcel Exp $
- * $FreeBSD: src/sys/sys/elf64.h,v 1.10.14.1 2005/12/30 22:13:58 marcel Exp $
- * $FreeBSD: src/sys/sys/elf_common.h,v 1.15.8.1 2005/12/30 22:13:58 marcel Exp $
- * $FreeBSD: src/sys/alpha/include/elf.h,v 1.14 2003/09/25 01:10:22 peter Exp $
- * $FreeBSD: src/sys/amd64/include/elf.h,v 1.18 2004/08/03 08:21:48 dfr Exp $
- * $FreeBSD: src/sys/arm/include/elf.h,v 1.5.2.1 2006/06/30 21:42:52 cognet Exp $
- * $FreeBSD: src/sys/i386/include/elf.h,v 1.16 2004/08/02 19:12:17 dfr Exp $
- * $FreeBSD: src/sys/powerpc/include/elf.h,v 1.7 2004/11/02 09:47:01 ssouhlal Exp $
- * $FreeBSD: src/sys/sparc64/include/elf.h,v 1.12 2003/09/25 01:10:26 peter Exp $
- *
- * Copyright (c) 1996-1998 John D. Polstra.  All rights reserved.
- * Copyright (c) 2001 David E. O'Brien
- * Portions Copyright 2009 The Go Authors. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- */
-
-/*
- * ELF definitions that are independent of architecture or word size.
- */
-
-/*
- * Note header.  The ".note" section contains an array of notes.  Each
- * begins with this header, aligned to a word boundary.  Immediately
- * following the note header is n_namesz bytes of name, padded to the
- * next word boundary.  Then comes n_descsz bytes of descriptor, again
- * padded to a word boundary.  The values of n_namesz and n_descsz do
- * not include the padding.
- */
-type elfNote struct {
-	nNamesz uint32
-	nDescsz uint32
-	nType   uint32
-}
-
-const (
-	EI_MAG0              = 0
-	EI_MAG1              = 1
-	EI_MAG2              = 2
-	EI_MAG3              = 3
-	EI_CLASS             = 4
-	EI_DATA              = 5
-	EI_VERSION           = 6
-	EI_OSABI             = 7
-	EI_ABIVERSION        = 8
-	OLD_EI_BRAND         = 8
-	EI_PAD               = 9
-	EI_NIDENT            = 16
-	ELFMAG0              = 0x7f
-	ELFMAG1              = 'E'
-	ELFMAG2              = 'L'
-	ELFMAG3              = 'F'
-	SELFMAG              = 4
-	EV_NONE              = 0
-	EV_CURRENT           = 1
-	ELFCLASSNONE         = 0
-	ELFCLASS32           = 1
-	ELFCLASS64           = 2
-	ELFDATANONE          = 0
-	ELFDATA2LSB          = 1
-	ELFDATA2MSB          = 2
-	ELFOSABI_NONE        = 0
-	ELFOSABI_HPUX        = 1
-	ELFOSABI_NETBSD      = 2
-	ELFOSABI_LINUX       = 3
-	ELFOSABI_HURD        = 4
-	ELFOSABI_86OPEN      = 5
-	ELFOSABI_SOLARIS     = 6
-	ELFOSABI_AIX         = 7
-	ELFOSABI_IRIX        = 8
-	ELFOSABI_FREEBSD     = 9
-	ELFOSABI_TRU64       = 10
-	ELFOSABI_MODESTO     = 11
-	ELFOSABI_OPENBSD     = 12
-	ELFOSABI_OPENVMS     = 13
-	ELFOSABI_NSK         = 14
-	ELFOSABI_ARM         = 97
-	ELFOSABI_STANDALONE  = 255
-	ELFOSABI_SYSV        = ELFOSABI_NONE
-	ELFOSABI_MONTEREY    = ELFOSABI_AIX
-	ET_NONE              = 0
-	ET_REL               = 1
-	ET_EXEC              = 2
-	ET_DYN               = 3
-	ET_CORE              = 4
-	ET_LOOS              = 0xfe00
-	ET_HIOS              = 0xfeff
-	ET_LOPROC            = 0xff00
-	ET_HIPROC            = 0xffff
-	EM_NONE              = 0
-	EM_M32               = 1
-	EM_SPARC             = 2
-	EM_386               = 3
-	EM_68K               = 4
-	EM_88K               = 5
-	EM_860               = 7
-	EM_MIPS              = 8
-	EM_S370              = 9
-	EM_MIPS_RS3_LE       = 10
-	EM_PARISC            = 15
-	EM_VPP500            = 17
-	EM_SPARC32PLUS       = 18
-	EM_960               = 19
-	EM_PPC               = 20
-	EM_PPC64             = 21
-	EM_S390              = 22
-	EM_V800              = 36
-	EM_FR20              = 37
-	EM_RH32              = 38
-	EM_RCE               = 39
-	EM_ARM               = 40
-	EM_SH                = 42
-	EM_SPARCV9           = 43
-	EM_TRICORE           = 44
-	EM_ARC               = 45
-	EM_H8_300            = 46
-	EM_H8_300H           = 47
-	EM_H8S               = 48
-	EM_H8_500            = 49
-	EM_IA_64             = 50
-	EM_MIPS_X            = 51
-	EM_COLDFIRE          = 52
-	EM_68HC12            = 53
-	EM_MMA               = 54
-	EM_PCP               = 55
-	EM_NCPU              = 56
-	EM_NDR1              = 57
-	EM_STARCORE          = 58
-	EM_ME16              = 59
-	EM_ST100             = 60
-	EM_TINYJ             = 61
-	EM_X86_64            = 62
-	EM_AARCH64           = 183
-	EM_486               = 6
-	EM_MIPS_RS4_BE       = 10
-	EM_ALPHA_STD         = 41
-	EM_ALPHA             = 0x9026
-	EM_RISCV             = 243
-	SHN_UNDEF            = 0
-	SHN_LORESERVE        = 0xff00
-	SHN_LOPROC           = 0xff00
-	SHN_HIPROC           = 0xff1f
-	SHN_LOOS             = 0xff20
-	SHN_HIOS             = 0xff3f
-	SHN_ABS              = 0xfff1
-	SHN_COMMON           = 0xfff2
-	SHN_XINDEX           = 0xffff
-	SHN_HIRESERVE        = 0xffff
-	SHT_NULL             = 0
-	SHT_PROGBITS         = 1
-	SHT_SYMTAB           = 2
-	SHT_STRTAB           = 3
-	SHT_RELA             = 4
-	SHT_HASH             = 5
-	SHT_DYNAMIC          = 6
-	SHT_NOTE             = 7
-	SHT_NOBITS           = 8
-	SHT_REL              = 9
-	SHT_SHLIB            = 10
-	SHT_DYNSYM           = 11
-	SHT_INIT_ARRAY       = 14
-	SHT_FINI_ARRAY       = 15
-	SHT_PREINIT_ARRAY    = 16
-	SHT_GROUP            = 17
-	SHT_SYMTAB_SHNDX     = 18
-	SHT_LOOS             = 0x60000000
-	SHT_HIOS             = 0x6fffffff
-	SHT_GNU_VERDEF       = 0x6ffffffd
-	SHT_GNU_VERNEED      = 0x6ffffffe
-	SHT_GNU_VERSYM       = 0x6fffffff
-	SHT_LOPROC           = 0x70000000
-	SHT_ARM_ATTRIBUTES   = 0x70000003
-	SHT_HIPROC           = 0x7fffffff
-	SHT_LOUSER           = 0x80000000
-	SHT_HIUSER           = 0xffffffff
-	SHF_WRITE            = 0x1
-	SHF_ALLOC            = 0x2
-	SHF_EXECINSTR        = 0x4
-	SHF_MERGE            = 0x10
-	SHF_STRINGS          = 0x20
-	SHF_INFO_LINK        = 0x40
-	SHF_LINK_ORDER       = 0x80
-	SHF_OS_NONCONFORMING = 0x100
-	SHF_GROUP            = 0x200
-	SHF_TLS              = 0x400
-	SHF_MASKOS           = 0x0ff00000
-	SHF_MASKPROC         = 0xf0000000
-	PT_NULL              = 0
-	PT_LOAD              = 1
-	PT_DYNAMIC           = 2
-	PT_INTERP            = 3
-	PT_NOTE              = 4
-	PT_SHLIB             = 5
-	PT_PHDR              = 6
-	PT_TLS               = 7
-	PT_LOOS              = 0x60000000
-	PT_HIOS              = 0x6fffffff
-	PT_LOPROC            = 0x70000000
-	PT_HIPROC            = 0x7fffffff
-	PT_GNU_STACK         = 0x6474e551
-	PT_GNU_RELRO         = 0x6474e552
-	PT_PAX_FLAGS         = 0x65041580
-	PT_SUNWSTACK         = 0x6ffffffb
-	PF_X                 = 0x1
-	PF_W                 = 0x2
-	PF_R                 = 0x4
-	PF_MASKOS            = 0x0ff00000
-	PF_MASKPROC          = 0xf0000000
-	DT_NULL              = 0
-	DT_NEEDED            = 1
-	DT_PLTRELSZ          = 2
-	DT_PLTGOT            = 3
-	DT_HASH              = 4
-	DT_STRTAB            = 5
-	DT_SYMTAB            = 6
-	DT_RELA              = 7
-	DT_RELASZ            = 8
-	DT_RELAENT           = 9
-	DT_STRSZ             = 10
-	DT_SYMENT            = 11
-	DT_INIT              = 12
-	DT_FINI              = 13
-	DT_SONAME            = 14
-	DT_RPATH             = 15
-	DT_SYMBOLIC          = 16
-	DT_REL               = 17
-	DT_RELSZ             = 18
-	DT_RELENT            = 19
-	DT_PLTREL            = 20
-	DT_DEBUG             = 21
-	DT_TEXTREL           = 22
-	DT_JMPREL            = 23
-	DT_BIND_NOW          = 24
-	DT_INIT_ARRAY        = 25
-	DT_FINI_ARRAY        = 26
-	DT_INIT_ARRAYSZ      = 27
-	DT_FINI_ARRAYSZ      = 28
-	DT_RUNPATH           = 29
-	DT_FLAGS             = 30
-	DT_ENCODING          = 32
-	DT_PREINIT_ARRAY     = 32
-	DT_PREINIT_ARRAYSZ   = 33
-	DT_LOOS              = 0x6000000d
-	DT_HIOS              = 0x6ffff000
-	DT_LOPROC            = 0x70000000
-	DT_HIPROC            = 0x7fffffff
-	DT_VERNEED           = 0x6ffffffe
-	DT_VERNEEDNUM        = 0x6fffffff
-	DT_VERSYM            = 0x6ffffff0
-	DT_PPC64_GLINK       = DT_LOPROC + 0
-	DT_PPC64_OPT         = DT_LOPROC + 3
-	DF_ORIGIN            = 0x0001
-	DF_SYMBOLIC          = 0x0002
-	DF_TEXTREL           = 0x0004
-	DF_BIND_NOW          = 0x0008
-	DF_STATIC_TLS        = 0x0010
-	NT_PRSTATUS          = 1
-	NT_FPREGSET          = 2
-	NT_PRPSINFO          = 3
-	STB_LOCAL            = 0
-	STB_GLOBAL           = 1
-	STB_WEAK             = 2
-	STB_LOOS             = 10
-	STB_HIOS             = 12
-	STB_LOPROC           = 13
-	STB_HIPROC           = 15
-	STT_NOTYPE           = 0
-	STT_OBJECT           = 1
-	STT_FUNC             = 2
-	STT_SECTION          = 3
-	STT_FILE             = 4
-	STT_COMMON           = 5
-	STT_TLS              = 6
-	STT_LOOS             = 10
-	STT_HIOS             = 12
-	STT_LOPROC           = 13
-	STT_HIPROC           = 15
-	STV_DEFAULT          = 0x0
-	STV_INTERNAL         = 0x1
-	STV_HIDDEN           = 0x2
-	STV_PROTECTED        = 0x3
-	STN_UNDEF            = 0
-)
-
-/* For accessing the fields of r_info. */
-
-/* For constructing r_info from field values. */
-
-/*
- * Relocation types.
- */
-const (
-	ARM_MAGIC_TRAMP_NUMBER = 0x5c000003
-)
-
-/*
- * Symbol table entries.
- */
-
-/* For accessing the fields of st_info. */
-
-/* For constructing st_info from field values. */
-
-/* For accessing the fields of st_other. */
-
-/*
- * ELF header.
- */
-type ElfEhdr struct {
-	ident     [EI_NIDENT]uint8
-	type_     uint16
-	machine   uint16
-	version   uint32
-	entry     uint64
-	phoff     uint64
-	shoff     uint64
-	flags     uint32
-	ehsize    uint16
-	phentsize uint16
-	phnum     uint16
-	shentsize uint16
-	shnum     uint16
-	shstrndx  uint16
-}
-
-/*
- * Section header.
- */
-type ElfShdr struct {
-	name      uint32
-	type_     uint32
-	flags     uint64
-	addr      uint64
-	off       uint64
-	size      uint64
-	link      uint32
-	info      uint32
-	addralign uint64
-	entsize   uint64
-	shnum     int
-}
-
-/*
- * Program header.
- */
-type ElfPhdr struct {
-	type_  uint32
-	flags  uint32
-	off    uint64
-	vaddr  uint64
-	paddr  uint64
-	filesz uint64
-	memsz  uint64
-	align  uint64
-}
-
-/* For accessing the fields of r_info. */
-
-/* For constructing r_info from field values. */
-
-/*
- * Symbol table entries.
- */
-
-/* For accessing the fields of st_info. */
-
-/* For constructing st_info from field values. */
-
-/* For accessing the fields of st_other. */
-
-/*
- * Go linker interface
- */
-const (
-	ELF64HDRSIZE  = 64
-	ELF64PHDRSIZE = 56
-	ELF64SHDRSIZE = 64
-	ELF64RELSIZE  = 16
-	ELF64RELASIZE = 24
-	ELF64SYMSIZE  = 24
-	ELF32HDRSIZE  = 52
-	ELF32PHDRSIZE = 32
-	ELF32SHDRSIZE = 40
-	ELF32SYMSIZE  = 16
-	ELF32RELSIZE  = 8
-)
-
-/*
- * The interface uses the 64-bit structures always,
- * to avoid code duplication.  The writers know how to
- * marshal a 32-bit representation from the 64-bit structure.
- */
-
-var Elfstrdat []byte
-
-/*
- * Total amount of space to reserve at the start of the file
- * for Header, PHeaders, SHeaders, and interp.
- * May waste some.
- * On FreeBSD, cannot be larger than a page.
- */
-const (
-	ELFRESERVE = 4096
-)
-
-/*
- * We use the 64-bit data structures on both 32- and 64-bit machines
- * in order to write the code just once.  The 64-bit data structure is
- * written in the 32-bit format on the 32-bit machines.
- */
-const (
-	NSECT = 400
-)
-
-var (
-	Nelfsym = 1
-
-	elf64 bool
-	// Either ".rel" or ".rela" depending on which type of relocation the
-	// target platform uses.
-	elfRelType string
-
-	ehdr ElfEhdr
-	phdr [NSECT]*ElfPhdr
-	shdr [NSECT]*ElfShdr
-
-	interp string
-)
-
-type Elfstring struct {
-	s   string
-	off int
-}
-
-var elfstr [100]Elfstring
-
-var nelfstr int
-
-var buildinfo []byte
-
-/*
- Initialize the global variable that describes the ELF header. It will be updated as
- we write section and prog headers.
-*/
-func Elfinit(ctxt *Link) {
-	ctxt.IsELF = true
-
-	if ctxt.Arch.InFamily(sys.AMD64, sys.ARM64, sys.MIPS64, sys.PPC64, sys.RISCV64, sys.S390X) {
-		elfRelType = ".rela"
-	} else {
-		elfRelType = ".rel"
-	}
-
-	switch ctxt.Arch.Family {
-	// 64-bit architectures
-	case sys.PPC64, sys.S390X:
-		if ctxt.Arch.ByteOrder == binary.BigEndian {
-			ehdr.flags = 1 /* Version 1 ABI */
-		} else {
-			ehdr.flags = 2 /* Version 2 ABI */
-		}
-		fallthrough
-	case sys.AMD64, sys.ARM64, sys.MIPS64, sys.RISCV64:
-		if ctxt.Arch.Family == sys.MIPS64 {
-			ehdr.flags = 0x20000004 /* MIPS 3 CPIC */
-		}
-		elf64 = true
-
-		ehdr.phoff = ELF64HDRSIZE      /* Must be ELF64HDRSIZE: first PHdr must follow ELF header */
-		ehdr.shoff = ELF64HDRSIZE      /* Will move as we add PHeaders */
-		ehdr.ehsize = ELF64HDRSIZE     /* Must be ELF64HDRSIZE */
-		ehdr.phentsize = ELF64PHDRSIZE /* Must be ELF64PHDRSIZE */
-		ehdr.shentsize = ELF64SHDRSIZE /* Must be ELF64SHDRSIZE */
-
-	// 32-bit architectures
-	case sys.ARM, sys.MIPS:
-		if ctxt.Arch.Family == sys.ARM {
-			// we use EABI on linux/arm, freebsd/arm, netbsd/arm.
-			if ctxt.HeadType == objabi.Hlinux || ctxt.HeadType == objabi.Hfreebsd || ctxt.HeadType == objabi.Hnetbsd {
-				// We set a value here that makes no indication of which
-				// float ABI the object uses, because this is information
-				// used by the dynamic linker to compare executables and
-				// shared libraries -- so it only matters for cgo calls, and
-				// the information properly comes from the object files
-				// produced by the host C compiler. parseArmAttributes in
-				// ldelf.go reads that information and updates this field as
-				// appropriate.
-				ehdr.flags = 0x5000002 // has entry point, Version5 EABI
-			}
-		} else if ctxt.Arch.Family == sys.MIPS {
-			ehdr.flags = 0x50001004 /* MIPS 32 CPIC O32*/
-		}
-		fallthrough
-	default:
-		ehdr.phoff = ELF32HDRSIZE
-		/* Must be ELF32HDRSIZE: first PHdr must follow ELF header */
-		ehdr.shoff = ELF32HDRSIZE      /* Will move as we add PHeaders */
-		ehdr.ehsize = ELF32HDRSIZE     /* Must be ELF32HDRSIZE */
-		ehdr.phentsize = ELF32PHDRSIZE /* Must be ELF32PHDRSIZE */
-		ehdr.shentsize = ELF32SHDRSIZE /* Must be ELF32SHDRSIZE */
-	}
-}
-
-// Make sure PT_LOAD is aligned properly and
-// that there is no gap,
-// correct ELF loaders will do this implicitly,
-// but buggy ELF loaders like the one in some
-// versions of QEMU and UPX won't.
-func fixElfPhdr(e *ElfPhdr) {
-	frag := int(e.vaddr & (e.align - 1))
-
-	e.off -= uint64(frag)
-	e.vaddr -= uint64(frag)
-	e.paddr -= uint64(frag)
-	e.filesz += uint64(frag)
-	e.memsz += uint64(frag)
-}
-
-func elf64phdr(out *OutBuf, e *ElfPhdr) {
-	if e.type_ == PT_LOAD {
-		fixElfPhdr(e)
-	}
-
-	out.Write32(e.type_)
-	out.Write32(e.flags)
-	out.Write64(e.off)
-	out.Write64(e.vaddr)
-	out.Write64(e.paddr)
-	out.Write64(e.filesz)
-	out.Write64(e.memsz)
-	out.Write64(e.align)
-}
-
-func elf32phdr(out *OutBuf, e *ElfPhdr) {
-	if e.type_ == PT_LOAD {
-		fixElfPhdr(e)
-	}
-
-	out.Write32(e.type_)
-	out.Write32(uint32(e.off))
-	out.Write32(uint32(e.vaddr))
-	out.Write32(uint32(e.paddr))
-	out.Write32(uint32(e.filesz))
-	out.Write32(uint32(e.memsz))
-	out.Write32(e.flags)
-	out.Write32(uint32(e.align))
-}
-
-func elf64shdr(out *OutBuf, e *ElfShdr) {
-	out.Write32(e.name)
-	out.Write32(e.type_)
-	out.Write64(e.flags)
-	out.Write64(e.addr)
-	out.Write64(e.off)
-	out.Write64(e.size)
-	out.Write32(e.link)
-	out.Write32(e.info)
-	out.Write64(e.addralign)
-	out.Write64(e.entsize)
-}
-
-func elf32shdr(out *OutBuf, e *ElfShdr) {
-	out.Write32(e.name)
-	out.Write32(e.type_)
-	out.Write32(uint32(e.flags))
-	out.Write32(uint32(e.addr))
-	out.Write32(uint32(e.off))
-	out.Write32(uint32(e.size))
-	out.Write32(e.link)
-	out.Write32(e.info)
-	out.Write32(uint32(e.addralign))
-	out.Write32(uint32(e.entsize))
-}
-
-func elfwriteshdrs(out *OutBuf) uint32 {
-	if elf64 {
-		for i := 0; i < int(ehdr.shnum); i++ {
-			elf64shdr(out, shdr[i])
-		}
-		return uint32(ehdr.shnum) * ELF64SHDRSIZE
-	}
-
-	for i := 0; i < int(ehdr.shnum); i++ {
-		elf32shdr(out, shdr[i])
-	}
-	return uint32(ehdr.shnum) * ELF32SHDRSIZE
-}
-
-func elfsetstring(s *sym.Symbol, str string, off int) {
-	if nelfstr >= len(elfstr) {
-		Errorf(s, "too many elf strings")
-		errorexit()
-	}
-
-	elfstr[nelfstr].s = str
-	elfstr[nelfstr].off = off
-	nelfstr++
-}
-
-func elfwritephdrs(out *OutBuf) uint32 {
-	if elf64 {
-		for i := 0; i < int(ehdr.phnum); i++ {
-			elf64phdr(out, phdr[i])
-		}
-		return uint32(ehdr.phnum) * ELF64PHDRSIZE
-	}
-
-	for i := 0; i < int(ehdr.phnum); i++ {
-		elf32phdr(out, phdr[i])
-	}
-	return uint32(ehdr.phnum) * ELF32PHDRSIZE
-}
-
-func newElfPhdr() *ElfPhdr {
-	e := new(ElfPhdr)
-	if ehdr.phnum >= NSECT {
-		Errorf(nil, "too many phdrs")
-	} else {
-		phdr[ehdr.phnum] = e
-		ehdr.phnum++
-	}
-	if elf64 {
-		ehdr.shoff += ELF64PHDRSIZE
-	} else {
-		ehdr.shoff += ELF32PHDRSIZE
-	}
-	return e
-}
-
-func newElfShdr(name int64) *ElfShdr {
-	e := new(ElfShdr)
-	e.name = uint32(name)
-	e.shnum = int(ehdr.shnum)
-	if ehdr.shnum >= NSECT {
-		Errorf(nil, "too many shdrs")
-	} else {
-		shdr[ehdr.shnum] = e
-		ehdr.shnum++
-	}
-
-	return e
-}
-
-func getElfEhdr() *ElfEhdr {
-	return &ehdr
-}
-
-func elf64writehdr(out *OutBuf) uint32 {
-	out.Write(ehdr.ident[:])
-	out.Write16(ehdr.type_)
-	out.Write16(ehdr.machine)
-	out.Write32(ehdr.version)
-	out.Write64(ehdr.entry)
-	out.Write64(ehdr.phoff)
-	out.Write64(ehdr.shoff)
-	out.Write32(ehdr.flags)
-	out.Write16(ehdr.ehsize)
-	out.Write16(ehdr.phentsize)
-	out.Write16(ehdr.phnum)
-	out.Write16(ehdr.shentsize)
-	out.Write16(ehdr.shnum)
-	out.Write16(ehdr.shstrndx)
-	return ELF64HDRSIZE
-}
-
-func elf32writehdr(out *OutBuf) uint32 {
-	out.Write(ehdr.ident[:])
-	out.Write16(ehdr.type_)
-	out.Write16(ehdr.machine)
-	out.Write32(ehdr.version)
-	out.Write32(uint32(ehdr.entry))
-	out.Write32(uint32(ehdr.phoff))
-	out.Write32(uint32(ehdr.shoff))
-	out.Write32(ehdr.flags)
-	out.Write16(ehdr.ehsize)
-	out.Write16(ehdr.phentsize)
-	out.Write16(ehdr.phnum)
-	out.Write16(ehdr.shentsize)
-	out.Write16(ehdr.shnum)
-	out.Write16(ehdr.shstrndx)
-	return ELF32HDRSIZE
-}
-
-func elfwritehdr(out *OutBuf) uint32 {
-	if elf64 {
-		return elf64writehdr(out)
-	}
-	return elf32writehdr(out)
-}
-
-/* Taken directly from the definition document for ELF64 */
-func elfhash(name string) uint32 {
-	var h uint32
-	for i := 0; i < len(name); i++ {
-		h = (h << 4) + uint32(name[i])
-		if g := h & 0xf0000000; g != 0 {
-			h ^= g >> 24
-		}
-		h &= 0x0fffffff
-	}
-	return h
-}
-
-func Elfwritedynent(ctxt *Link, s *sym.Symbol, tag int, val uint64) {
-	if elf64 {
-		s.AddUint64(ctxt.Arch, uint64(tag))
-		s.AddUint64(ctxt.Arch, val)
-	} else {
-		s.AddUint32(ctxt.Arch, uint32(tag))
-		s.AddUint32(ctxt.Arch, uint32(val))
-	}
-}
-
-func elfwritedynentsym(ctxt *Link, s *sym.Symbol, tag int, t *sym.Symbol) {
-	Elfwritedynentsymplus(ctxt, s, tag, t, 0)
-}
-
-func Elfwritedynentsymplus(ctxt *Link, s *sym.Symbol, tag int, t *sym.Symbol, add int64) {
-	if elf64 {
-		s.AddUint64(ctxt.Arch, uint64(tag))
-	} else {
-		s.AddUint32(ctxt.Arch, uint32(tag))
-	}
-	s.AddAddrPlus(ctxt.Arch, t, add)
-}
-
-func elfwritedynentsymsize(ctxt *Link, s *sym.Symbol, tag int, t *sym.Symbol) {
-	if elf64 {
-		s.AddUint64(ctxt.Arch, uint64(tag))
-	} else {
-		s.AddUint32(ctxt.Arch, uint32(tag))
-	}
-	s.AddSize(ctxt.Arch, t)
-}
-
-func elfinterp(sh *ElfShdr, startva uint64, resoff uint64, p string) int {
-	interp = p
-	n := len(interp) + 1
-	sh.addr = startva + resoff - uint64(n)
-	sh.off = resoff - uint64(n)
-	sh.size = uint64(n)
-
-	return n
-}
-
-func elfwriteinterp(out *OutBuf) int {
-	sh := elfshname(".interp")
-	out.SeekSet(int64(sh.off))
-	out.WriteString(interp)
-	out.Write8(0)
-	return int(sh.size)
-}
-
-func elfnote(sh *ElfShdr, startva uint64, resoff uint64, sz int) int {
-	n := 3*4 + uint64(sz) + resoff%4
-
-	sh.type_ = SHT_NOTE
-	sh.flags = SHF_ALLOC
-	sh.addralign = 4
-	sh.addr = startva + resoff - n
-	sh.off = resoff - n
-	sh.size = n - resoff%4
-
-	return int(n)
-}
-
-func elfwritenotehdr(out *OutBuf, str string, namesz uint32, descsz uint32, tag uint32) *ElfShdr {
-	sh := elfshname(str)
-
-	// Write Elf_Note header.
-	out.SeekSet(int64(sh.off))
-
-	out.Write32(namesz)
-	out.Write32(descsz)
-	out.Write32(tag)
-
-	return sh
-}
-
-// NetBSD Signature (as per sys/exec_elf.h)
-const (
-	ELF_NOTE_NETBSD_NAMESZ  = 7
-	ELF_NOTE_NETBSD_DESCSZ  = 4
-	ELF_NOTE_NETBSD_TAG     = 1
-	ELF_NOTE_NETBSD_VERSION = 700000000 /* NetBSD 7.0 */
-)
-
-var ELF_NOTE_NETBSD_NAME = []byte("NetBSD\x00")
-
-func elfnetbsdsig(sh *ElfShdr, startva uint64, resoff uint64) int {
-	n := int(Rnd(ELF_NOTE_NETBSD_NAMESZ, 4) + Rnd(ELF_NOTE_NETBSD_DESCSZ, 4))
-	return elfnote(sh, startva, resoff, n)
-}
-
-func elfwritenetbsdsig(out *OutBuf) int {
-	// Write Elf_Note header.
-	sh := elfwritenotehdr(out, ".note.netbsd.ident", ELF_NOTE_NETBSD_NAMESZ, ELF_NOTE_NETBSD_DESCSZ, ELF_NOTE_NETBSD_TAG)
-
-	if sh == nil {
-		return 0
-	}
-
-	// Followed by NetBSD string and version.
-	out.Write(ELF_NOTE_NETBSD_NAME)
-	out.Write8(0)
-	out.Write32(ELF_NOTE_NETBSD_VERSION)
-
-	return int(sh.size)
-}
-
-// The race detector can't handle ASLR (address space layout randomization).
-// ASLR is on by default for NetBSD, so we turn the ASLR off eplicitly
-// using a magic elf Note when building race binaries.
-
-func elfnetbsdpax(sh *ElfShdr, startva uint64, resoff uint64) int {
-	n := int(Rnd(4, 4) + Rnd(4, 4))
-	return elfnote(sh, startva, resoff, n)
-}
-
-func elfwritenetbsdpax(out *OutBuf) int {
-	sh := elfwritenotehdr(out, ".note.netbsd.pax", 4 /* length of PaX\x00 */, 4 /* length of flags */, 0x03 /* PaX type */)
-	if sh == nil {
-		return 0
-	}
-	out.Write([]byte("PaX\x00"))
-	out.Write32(0x20) // 0x20 = Force disable ASLR
-	return int(sh.size)
-}
-
-// OpenBSD Signature
-const (
-	ELF_NOTE_OPENBSD_NAMESZ  = 8
-	ELF_NOTE_OPENBSD_DESCSZ  = 4
-	ELF_NOTE_OPENBSD_TAG     = 1
-	ELF_NOTE_OPENBSD_VERSION = 0
-)
-
-var ELF_NOTE_OPENBSD_NAME = []byte("OpenBSD\x00")
-
-func elfopenbsdsig(sh *ElfShdr, startva uint64, resoff uint64) int {
-	n := ELF_NOTE_OPENBSD_NAMESZ + ELF_NOTE_OPENBSD_DESCSZ
-	return elfnote(sh, startva, resoff, n)
-}
-
-func elfwriteopenbsdsig(out *OutBuf) int {
-	// Write Elf_Note header.
-	sh := elfwritenotehdr(out, ".note.openbsd.ident", ELF_NOTE_OPENBSD_NAMESZ, ELF_NOTE_OPENBSD_DESCSZ, ELF_NOTE_OPENBSD_TAG)
-
-	if sh == nil {
-		return 0
-	}
-
-	// Followed by OpenBSD string and version.
-	out.Write(ELF_NOTE_OPENBSD_NAME)
-
-	out.Write32(ELF_NOTE_OPENBSD_VERSION)
-
-	return int(sh.size)
-}
-
-func addbuildinfo(val string) {
-	if !strings.HasPrefix(val, "0x") {
-		Exitf("-B argument must start with 0x: %s", val)
-	}
-
-	ov := val
-	val = val[2:]
-
-	const maxLen = 32
-	if hex.DecodedLen(len(val)) > maxLen {
-		Exitf("-B option too long (max %d digits): %s", maxLen, ov)
-	}
-
-	b, err := hex.DecodeString(val)
-	if err != nil {
-		if err == hex.ErrLength {
-			Exitf("-B argument must have even number of digits: %s", ov)
-		}
-		if inv, ok := err.(hex.InvalidByteError); ok {
-			Exitf("-B argument contains invalid hex digit %c: %s", byte(inv), ov)
-		}
-		Exitf("-B argument contains invalid hex: %s", ov)
-	}
-
-	buildinfo = b
-}
-
-// Build info note
-const (
-	ELF_NOTE_BUILDINFO_NAMESZ = 4
-	ELF_NOTE_BUILDINFO_TAG    = 3
-)
-
-var ELF_NOTE_BUILDINFO_NAME = []byte("GNU\x00")
-
-func elfbuildinfo(sh *ElfShdr, startva uint64, resoff uint64) int {
-	n := int(ELF_NOTE_BUILDINFO_NAMESZ + Rnd(int64(len(buildinfo)), 4))
-	return elfnote(sh, startva, resoff, n)
-}
-
-func elfgobuildid(sh *ElfShdr, startva uint64, resoff uint64) int {
-	n := len(ELF_NOTE_GO_NAME) + int(Rnd(int64(len(*flagBuildid)), 4))
-	return elfnote(sh, startva, resoff, n)
-}
-
-func elfwritebuildinfo(out *OutBuf) int {
-	sh := elfwritenotehdr(out, ".note.gnu.build-id", ELF_NOTE_BUILDINFO_NAMESZ, uint32(len(buildinfo)), ELF_NOTE_BUILDINFO_TAG)
-	if sh == nil {
-		return 0
-	}
-
-	out.Write(ELF_NOTE_BUILDINFO_NAME)
-	out.Write(buildinfo)
-	var zero = make([]byte, 4)
-	out.Write(zero[:int(Rnd(int64(len(buildinfo)), 4)-int64(len(buildinfo)))])
-
-	return int(sh.size)
-}
-
-func elfwritegobuildid(out *OutBuf) int {
-	sh := elfwritenotehdr(out, ".note.go.buildid", uint32(len(ELF_NOTE_GO_NAME)), uint32(len(*flagBuildid)), ELF_NOTE_GOBUILDID_TAG)
-	if sh == nil {
-		return 0
-	}
-
-	out.Write(ELF_NOTE_GO_NAME)
-	out.Write([]byte(*flagBuildid))
-	var zero = make([]byte, 4)
-	out.Write(zero[:int(Rnd(int64(len(*flagBuildid)), 4)-int64(len(*flagBuildid)))])
-
-	return int(sh.size)
-}
-
-// Go specific notes
-const (
-	ELF_NOTE_GOPKGLIST_TAG = 1
-	ELF_NOTE_GOABIHASH_TAG = 2
-	ELF_NOTE_GODEPS_TAG    = 3
-	ELF_NOTE_GOBUILDID_TAG = 4
-)
-
-var ELF_NOTE_GO_NAME = []byte("Go\x00\x00")
-
-var elfverneed int
-
-type Elfaux struct {
-	next *Elfaux
-	num  int
-	vers string
-}
-
-type Elflib struct {
-	next *Elflib
-	aux  *Elfaux
-	file string
-}
-
-func addelflib(list **Elflib, file string, vers string) *Elfaux {
-	var lib *Elflib
-
-	for lib = *list; lib != nil; lib = lib.next {
-		if lib.file == file {
-			goto havelib
-		}
-	}
-	lib = new(Elflib)
-	lib.next = *list
-	lib.file = file
-	*list = lib
-
-havelib:
-	for aux := lib.aux; aux != nil; aux = aux.next {
-		if aux.vers == vers {
-			return aux
-		}
-	}
-	aux := new(Elfaux)
-	aux.next = lib.aux
-	aux.vers = vers
-	lib.aux = aux
-
-	return aux
-}
-
-func elfdynhash(ctxt *Link) {
-	if !ctxt.IsELF {
-		return
-	}
-
-	nsym := Nelfsym
-	s := ctxt.Syms.Lookup(".hash", 0)
-	s.Type = sym.SELFROSECT
-	s.Attr |= sym.AttrReachable
-
-	i := nsym
-	nbucket := 1
-	for i > 0 {
-		nbucket++
-		i >>= 1
-	}
-
-	var needlib *Elflib
-	need := make([]*Elfaux, nsym)
-	chain := make([]uint32, nsym)
-	buckets := make([]uint32, nbucket)
-
-	for _, sy := range ctxt.Syms.Allsym {
-		if sy.Dynid <= 0 {
-			continue
-		}
-
-		if sy.Dynimpvers() != "" {
-			need[sy.Dynid] = addelflib(&needlib, sy.Dynimplib(), sy.Dynimpvers())
-		}
-
-		name := sy.Extname()
-		hc := elfhash(name)
-
-		b := hc % uint32(nbucket)
-		chain[sy.Dynid] = buckets[b]
-		buckets[b] = uint32(sy.Dynid)
-	}
-
-	// s390x (ELF64) hash table entries are 8 bytes
-	if ctxt.Arch.Family == sys.S390X {
-		s.AddUint64(ctxt.Arch, uint64(nbucket))
-		s.AddUint64(ctxt.Arch, uint64(nsym))
-		for i := 0; i < nbucket; i++ {
-			s.AddUint64(ctxt.Arch, uint64(buckets[i]))
-		}
-		for i := 0; i < nsym; i++ {
-			s.AddUint64(ctxt.Arch, uint64(chain[i]))
-		}
-	} else {
-		s.AddUint32(ctxt.Arch, uint32(nbucket))
-		s.AddUint32(ctxt.Arch, uint32(nsym))
-		for i := 0; i < nbucket; i++ {
-			s.AddUint32(ctxt.Arch, buckets[i])
-		}
-		for i := 0; i < nsym; i++ {
-			s.AddUint32(ctxt.Arch, chain[i])
-		}
-	}
-
-	// version symbols
-	dynstr := ctxt.Syms.Lookup(".dynstr", 0)
-
-	s = ctxt.Syms.Lookup(".gnu.version_r", 0)
-	i = 2
-	nfile := 0
-	for l := needlib; l != nil; l = l.next {
-		nfile++
-
-		// header
-		s.AddUint16(ctxt.Arch, 1) // table version
-		j := 0
-		for x := l.aux; x != nil; x = x.next {
-			j++
-		}
-		s.AddUint16(ctxt.Arch, uint16(j))                         // aux count
-		s.AddUint32(ctxt.Arch, uint32(Addstring(dynstr, l.file))) // file string offset
-		s.AddUint32(ctxt.Arch, 16)                                // offset from header to first aux
-		if l.next != nil {
-			s.AddUint32(ctxt.Arch, 16+uint32(j)*16) // offset from this header to next
-		} else {
-			s.AddUint32(ctxt.Arch, 0)
-		}
-
-		for x := l.aux; x != nil; x = x.next {
-			x.num = i
-			i++
-
-			// aux struct
-			s.AddUint32(ctxt.Arch, elfhash(x.vers))                   // hash
-			s.AddUint16(ctxt.Arch, 0)                                 // flags
-			s.AddUint16(ctxt.Arch, uint16(x.num))                     // other - index we refer to this by
-			s.AddUint32(ctxt.Arch, uint32(Addstring(dynstr, x.vers))) // version string offset
-			if x.next != nil {
-				s.AddUint32(ctxt.Arch, 16) // offset from this aux to next
-			} else {
-				s.AddUint32(ctxt.Arch, 0)
-			}
-		}
-	}
-
-	// version references
-	s = ctxt.Syms.Lookup(".gnu.version", 0)
-
-	for i := 0; i < nsym; i++ {
-		if i == 0 {
-			s.AddUint16(ctxt.Arch, 0) // first entry - no symbol
-		} else if need[i] == nil {
-			s.AddUint16(ctxt.Arch, 1) // global
-		} else {
-			s.AddUint16(ctxt.Arch, uint16(need[i].num))
-		}
-	}
-
-	s = ctxt.Syms.Lookup(".dynamic", 0)
-	elfverneed = nfile
-	if elfverneed != 0 {
-		elfwritedynentsym(ctxt, s, DT_VERNEED, ctxt.Syms.Lookup(".gnu.version_r", 0))
-		Elfwritedynent(ctxt, s, DT_VERNEEDNUM, uint64(nfile))
-		elfwritedynentsym(ctxt, s, DT_VERSYM, ctxt.Syms.Lookup(".gnu.version", 0))
-	}
-
-	sy := ctxt.Syms.Lookup(elfRelType+".plt", 0)
-	if sy.Size > 0 {
-		if elfRelType == ".rela" {
-			Elfwritedynent(ctxt, s, DT_PLTREL, DT_RELA)
-		} else {
-			Elfwritedynent(ctxt, s, DT_PLTREL, DT_REL)
-		}
-		elfwritedynentsymsize(ctxt, s, DT_PLTRELSZ, sy)
-		elfwritedynentsym(ctxt, s, DT_JMPREL, sy)
-	}
-
-	Elfwritedynent(ctxt, s, DT_NULL, 0)
-}
-
-func elfphload(seg *sym.Segment) *ElfPhdr {
-	ph := newElfPhdr()
-	ph.type_ = PT_LOAD
-	if seg.Rwx&4 != 0 {
-		ph.flags |= PF_R
-	}
-	if seg.Rwx&2 != 0 {
-		ph.flags |= PF_W
-	}
-	if seg.Rwx&1 != 0 {
-		ph.flags |= PF_X
-	}
-	ph.vaddr = seg.Vaddr
-	ph.paddr = seg.Vaddr
-	ph.memsz = seg.Length
-	ph.off = seg.Fileoff
-	ph.filesz = seg.Filelen
-	ph.align = uint64(*FlagRound)
-
-	return ph
-}
-
-func elfphrelro(seg *sym.Segment) {
-	ph := newElfPhdr()
-	ph.type_ = PT_GNU_RELRO
-	ph.vaddr = seg.Vaddr
-	ph.paddr = seg.Vaddr
-	ph.memsz = seg.Length
-	ph.off = seg.Fileoff
-	ph.filesz = seg.Filelen
-	ph.align = uint64(*FlagRound)
-}
-
-func elfshname(name string) *ElfShdr {
-	for i := 0; i < nelfstr; i++ {
-		if name != elfstr[i].s {
-			continue
-		}
-		off := elfstr[i].off
-		for i = 0; i < int(ehdr.shnum); i++ {
-			sh := shdr[i]
-			if sh.name == uint32(off) {
-				return sh
-			}
-		}
-		return newElfShdr(int64(off))
-	}
-	Exitf("cannot find elf name %s", name)
-	return nil
-}
-
-// Create an ElfShdr for the section with name.
-// Create a duplicate if one already exists with that name
-func elfshnamedup(name string) *ElfShdr {
-	for i := 0; i < nelfstr; i++ {
-		if name == elfstr[i].s {
-			off := elfstr[i].off
-			return newElfShdr(int64(off))
-		}
-	}
-
-	Errorf(nil, "cannot find elf name %s", name)
-	errorexit()
-	return nil
-}
-
-func elfshalloc(sect *sym.Section) *ElfShdr {
-	sh := elfshname(sect.Name)
-	sect.Elfsect = sh
-	return sh
-}
-
-func elfshbits(linkmode LinkMode, sect *sym.Section) *ElfShdr {
-	var sh *ElfShdr
-
-	if sect.Name == ".text" {
-		if sect.Elfsect == nil {
-			sect.Elfsect = elfshnamedup(sect.Name)
-		}
-		sh = sect.Elfsect.(*ElfShdr)
-	} else {
-		sh = elfshalloc(sect)
-	}
-
-	// If this section has already been set up as a note, we assume type_ and
-	// flags are already correct, but the other fields still need filling in.
-	if sh.type_ == SHT_NOTE {
-		if linkmode != LinkExternal {
-			// TODO(mwhudson): the approach here will work OK when
-			// linking internally for notes that we want to be included
-			// in a loadable segment (e.g. the abihash note) but not for
-			// notes that we do not want to be mapped (e.g. the package
-			// list note). The real fix is probably to define new values
-			// for Symbol.Type corresponding to mapped and unmapped notes
-			// and handle them in dodata().
-			Errorf(nil, "sh.type_ == SHT_NOTE in elfshbits when linking internally")
-		}
-		sh.addralign = uint64(sect.Align)
-		sh.size = sect.Length
-		sh.off = sect.Seg.Fileoff + sect.Vaddr - sect.Seg.Vaddr
-		return sh
-	}
-	if sh.type_ > 0 {
-		return sh
-	}
-
-	if sect.Vaddr < sect.Seg.Vaddr+sect.Seg.Filelen {
-		sh.type_ = SHT_PROGBITS
-	} else {
-		sh.type_ = SHT_NOBITS
-	}
-	sh.flags = SHF_ALLOC
-	if sect.Rwx&1 != 0 {
-		sh.flags |= SHF_EXECINSTR
-	}
-	if sect.Rwx&2 != 0 {
-		sh.flags |= SHF_WRITE
-	}
-	if sect.Name == ".tbss" {
-		sh.flags |= SHF_TLS
-		sh.type_ = SHT_NOBITS
-	}
-	if strings.HasPrefix(sect.Name, ".debug") || strings.HasPrefix(sect.Name, ".zdebug") {
-		sh.flags = 0
-	}
-
-	if linkmode != LinkExternal {
-		sh.addr = sect.Vaddr
-	}
-	sh.addralign = uint64(sect.Align)
-	sh.size = sect.Length
-	if sect.Name != ".tbss" {
-		sh.off = sect.Seg.Fileoff + sect.Vaddr - sect.Seg.Vaddr
-	}
-
-	return sh
-}
-
-func elfshreloc(arch *sys.Arch, sect *sym.Section) *ElfShdr {
-	// If main section is SHT_NOBITS, nothing to relocate.
-	// Also nothing to relocate in .shstrtab or notes.
-	if sect.Vaddr >= sect.Seg.Vaddr+sect.Seg.Filelen {
-		return nil
-	}
-	if sect.Name == ".shstrtab" || sect.Name == ".tbss" {
-		return nil
-	}
-	if sect.Elfsect.(*ElfShdr).type_ == SHT_NOTE {
-		return nil
-	}
-
-	typ := SHT_REL
-	if elfRelType == ".rela" {
-		typ = SHT_RELA
-	}
-
-	sh := elfshname(elfRelType + sect.Name)
-	// There could be multiple text sections but each needs
-	// its own .rela.text.
-
-	if sect.Name == ".text" {
-		if sh.info != 0 && sh.info != uint32(sect.Elfsect.(*ElfShdr).shnum) {
-			sh = elfshnamedup(elfRelType + sect.Name)
-		}
-	}
-
-	sh.type_ = uint32(typ)
-	sh.entsize = uint64(arch.RegSize) * 2
-	if typ == SHT_RELA {
-		sh.entsize += uint64(arch.RegSize)
-	}
-	sh.link = uint32(elfshname(".symtab").shnum)
-	sh.info = uint32(sect.Elfsect.(*ElfShdr).shnum)
-	sh.off = sect.Reloff
-	sh.size = sect.Rellen
-	sh.addralign = uint64(arch.RegSize)
-	return sh
-}
-
-func elfrelocsect(ctxt *Link, sect *sym.Section, syms []*sym.Symbol) {
-	// If main section is SHT_NOBITS, nothing to relocate.
-	// Also nothing to relocate in .shstrtab.
-	if sect.Vaddr >= sect.Seg.Vaddr+sect.Seg.Filelen {
-		return
-	}
-	if sect.Name == ".shstrtab" {
-		return
-	}
-
-	sect.Reloff = uint64(ctxt.Out.Offset())
-	for i, s := range syms {
-		if !s.Attr.Reachable() {
-			continue
-		}
-		if uint64(s.Value) >= sect.Vaddr {
-			syms = syms[i:]
-			break
-		}
-	}
-
-	eaddr := int32(sect.Vaddr + sect.Length)
-	for _, s := range syms {
-		if !s.Attr.Reachable() {
-			continue
-		}
-		if s.Value >= int64(eaddr) {
-			break
-		}
-		for ri := range s.R {
-			r := &s.R[ri]
-			if r.Done {
-				continue
-			}
-			if r.Xsym == nil {
-				Errorf(s, "missing xsym in relocation %#v %#v", r.Sym.Name, s)
-				continue
-			}
-			if r.Xsym.ElfsymForReloc() == 0 {
-				Errorf(s, "reloc %d (%s) to non-elf symbol %s (outer=%s) %d (%s)", r.Type, sym.RelocName(ctxt.Arch, r.Type), r.Sym.Name, r.Xsym.Name, r.Sym.Type, r.Sym.Type)
-			}
-			if !r.Xsym.Attr.Reachable() {
-				Errorf(s, "unreachable reloc %d (%s) target %v", r.Type, sym.RelocName(ctxt.Arch, r.Type), r.Xsym.Name)
-			}
-			if !thearch.Elfreloc1(ctxt, r, int64(uint64(s.Value+int64(r.Off))-sect.Vaddr)) {
-				Errorf(s, "unsupported obj reloc %d (%s)/%d to %s", r.Type, sym.RelocName(ctxt.Arch, r.Type), r.Siz, r.Sym.Name)
-			}
-		}
-	}
-
-	sect.Rellen = uint64(ctxt.Out.Offset()) - sect.Reloff
-}
-
-func Elfemitreloc(ctxt *Link) {
-	for ctxt.Out.Offset()&7 != 0 {
-		ctxt.Out.Write8(0)
-	}
-
-	for _, sect := range Segtext.Sections {
-		if sect.Name == ".text" {
-			elfrelocsect(ctxt, sect, ctxt.Textp)
-		} else {
-			elfrelocsect(ctxt, sect, datap)
-		}
-	}
-
-	for _, sect := range Segrodata.Sections {
-		elfrelocsect(ctxt, sect, datap)
-	}
-	for _, sect := range Segrelrodata.Sections {
-		elfrelocsect(ctxt, sect, datap)
-	}
-	for _, sect := range Segdata.Sections {
-		elfrelocsect(ctxt, sect, datap)
-	}
-	for _, sect := range Segdwarf.Sections {
-		elfrelocsect(ctxt, sect, dwarfp)
-	}
-}
-
-func addgonote(ctxt *Link, sectionName string, tag uint32, desc []byte) {
-	s := ctxt.Syms.Lookup(sectionName, 0)
-	s.Attr |= sym.AttrReachable
-	s.Type = sym.SELFROSECT
-	// namesz
-	s.AddUint32(ctxt.Arch, uint32(len(ELF_NOTE_GO_NAME)))
-	// descsz
-	s.AddUint32(ctxt.Arch, uint32(len(desc)))
-	// tag
-	s.AddUint32(ctxt.Arch, tag)
-	// name + padding
-	s.P = append(s.P, ELF_NOTE_GO_NAME...)
-	for len(s.P)%4 != 0 {
-		s.P = append(s.P, 0)
-	}
-	// desc + padding
-	s.P = append(s.P, desc...)
-	for len(s.P)%4 != 0 {
-		s.P = append(s.P, 0)
-	}
-	s.Size = int64(len(s.P))
-	s.Align = 4
-}
-
-func (ctxt *Link) doelf() {
-	if !ctxt.IsELF {
-		return
-	}
-
-	/* predefine strings we need for section headers */
-	shstrtab := ctxt.Syms.Lookup(".shstrtab", 0)
-
-	shstrtab.Type = sym.SELFROSECT
-	shstrtab.Attr |= sym.AttrReachable
-
-	Addstring(shstrtab, "")
-	Addstring(shstrtab, ".text")
-	Addstring(shstrtab, ".noptrdata")
-	Addstring(shstrtab, ".data")
-	Addstring(shstrtab, ".bss")
-	Addstring(shstrtab, ".noptrbss")
-	Addstring(shstrtab, "__libfuzzer_extra_counters")
-	Addstring(shstrtab, ".go.buildinfo")
-
-	// generate .tbss section for dynamic internal linker or external
-	// linking, so that various binutils could correctly calculate
-	// PT_TLS size. See https://golang.org/issue/5200.
-	if !*FlagD || ctxt.LinkMode == LinkExternal {
-		Addstring(shstrtab, ".tbss")
-	}
-	if ctxt.HeadType == objabi.Hnetbsd {
-		Addstring(shstrtab, ".note.netbsd.ident")
-		if *flagRace {
-			Addstring(shstrtab, ".note.netbsd.pax")
-		}
-	}
-	if ctxt.HeadType == objabi.Hopenbsd {
-		Addstring(shstrtab, ".note.openbsd.ident")
-	}
-	if len(buildinfo) > 0 {
-		Addstring(shstrtab, ".note.gnu.build-id")
-	}
-	if *flagBuildid != "" {
-		Addstring(shstrtab, ".note.go.buildid")
-	}
-	Addstring(shstrtab, ".elfdata")
-	Addstring(shstrtab, ".rodata")
-	// See the comment about data.rel.ro.FOO section names in data.go.
-	relro_prefix := ""
-	if ctxt.UseRelro() {
-		Addstring(shstrtab, ".data.rel.ro")
-		relro_prefix = ".data.rel.ro"
-	}
-	Addstring(shstrtab, relro_prefix+".typelink")
-	Addstring(shstrtab, relro_prefix+".itablink")
-	Addstring(shstrtab, relro_prefix+".gosymtab")
-	Addstring(shstrtab, relro_prefix+".gopclntab")
-
-	if ctxt.LinkMode == LinkExternal {
-		*FlagD = true
-
-		Addstring(shstrtab, elfRelType+".text")
-		Addstring(shstrtab, elfRelType+".rodata")
-		Addstring(shstrtab, elfRelType+relro_prefix+".typelink")
-		Addstring(shstrtab, elfRelType+relro_prefix+".itablink")
-		Addstring(shstrtab, elfRelType+relro_prefix+".gosymtab")
-		Addstring(shstrtab, elfRelType+relro_prefix+".gopclntab")
-		Addstring(shstrtab, elfRelType+".noptrdata")
-		Addstring(shstrtab, elfRelType+".data")
-		if ctxt.UseRelro() {
-			Addstring(shstrtab, elfRelType+".data.rel.ro")
-		}
-		Addstring(shstrtab, elfRelType+".go.buildinfo")
-
-		// add a .note.GNU-stack section to mark the stack as non-executable
-		Addstring(shstrtab, ".note.GNU-stack")
-
-		if ctxt.BuildMode == BuildModeShared {
-			Addstring(shstrtab, ".note.go.abihash")
-			Addstring(shstrtab, ".note.go.pkg-list")
-			Addstring(shstrtab, ".note.go.deps")
-		}
-	}
-
-	hasinitarr := ctxt.linkShared
-
-	/* shared library initializer */
-	switch ctxt.BuildMode {
-	case BuildModeCArchive, BuildModeCShared, BuildModeShared, BuildModePlugin:
-		hasinitarr = true
-	}
-
-	if hasinitarr {
-		Addstring(shstrtab, ".init_array")
-		Addstring(shstrtab, elfRelType+".init_array")
-	}
-
-	if !*FlagS {
-		Addstring(shstrtab, ".symtab")
-		Addstring(shstrtab, ".strtab")
-		dwarfaddshstrings(ctxt, shstrtab)
-	}
-
-	Addstring(shstrtab, ".shstrtab")
-
-	if !*FlagD { /* -d suppresses dynamic loader format */
-		Addstring(shstrtab, ".interp")
-		Addstring(shstrtab, ".hash")
-		Addstring(shstrtab, ".got")
-		if ctxt.Arch.Family == sys.PPC64 {
-			Addstring(shstrtab, ".glink")
-		}
-		Addstring(shstrtab, ".got.plt")
-		Addstring(shstrtab, ".dynamic")
-		Addstring(shstrtab, ".dynsym")
-		Addstring(shstrtab, ".dynstr")
-		Addstring(shstrtab, elfRelType)
-		Addstring(shstrtab, elfRelType+".plt")
-
-		Addstring(shstrtab, ".plt")
-		Addstring(shstrtab, ".gnu.version")
-		Addstring(shstrtab, ".gnu.version_r")
-
-		/* dynamic symbol table - first entry all zeros */
-		s := ctxt.Syms.Lookup(".dynsym", 0)
-
-		s.Type = sym.SELFROSECT
-		s.Attr |= sym.AttrReachable
-		if elf64 {
-			s.Size += ELF64SYMSIZE
-		} else {
-			s.Size += ELF32SYMSIZE
-		}
-
-		/* dynamic string table */
-		s = ctxt.Syms.Lookup(".dynstr", 0)
-
-		s.Type = sym.SELFROSECT
-		s.Attr |= sym.AttrReachable
-		if s.Size == 0 {
-			Addstring(s, "")
-		}
-		dynstr := s
-
-		/* relocation table */
-		s = ctxt.Syms.Lookup(elfRelType, 0)
-		s.Attr |= sym.AttrReachable
-		s.Type = sym.SELFROSECT
-
-		/* global offset table */
-		s = ctxt.Syms.Lookup(".got", 0)
-
-		s.Attr |= sym.AttrReachable
-		s.Type = sym.SELFGOT // writable
-
-		/* ppc64 glink resolver */
-		if ctxt.Arch.Family == sys.PPC64 {
-			s := ctxt.Syms.Lookup(".glink", 0)
-			s.Attr |= sym.AttrReachable
-			s.Type = sym.SELFRXSECT
-		}
-
-		/* hash */
-		s = ctxt.Syms.Lookup(".hash", 0)
-
-		s.Attr |= sym.AttrReachable
-		s.Type = sym.SELFROSECT
-
-		s = ctxt.Syms.Lookup(".got.plt", 0)
-		s.Attr |= sym.AttrReachable
-		s.Type = sym.SELFSECT // writable
-
-		s = ctxt.Syms.Lookup(".plt", 0)
-
-		s.Attr |= sym.AttrReachable
-		if ctxt.Arch.Family == sys.PPC64 {
-			// In the ppc64 ABI, .plt is a data section
-			// written by the dynamic linker.
-			s.Type = sym.SELFSECT
-		} else {
-			s.Type = sym.SELFRXSECT
-		}
-
-		thearch.Elfsetupplt(ctxt)
-
-		s = ctxt.Syms.Lookup(elfRelType+".plt", 0)
-		s.Attr |= sym.AttrReachable
-		s.Type = sym.SELFROSECT
-
-		s = ctxt.Syms.Lookup(".gnu.version", 0)
-		s.Attr |= sym.AttrReachable
-		s.Type = sym.SELFROSECT
-
-		s = ctxt.Syms.Lookup(".gnu.version_r", 0)
-		s.Attr |= sym.AttrReachable
-		s.Type = sym.SELFROSECT
-
-		/* define dynamic elf table */
-		s = ctxt.Syms.Lookup(".dynamic", 0)
-
-		s.Attr |= sym.AttrReachable
-		s.Type = sym.SELFSECT // writable
-
-		/*
-		 * .dynamic table
-		 */
-		elfwritedynentsym(ctxt, s, DT_HASH, ctxt.Syms.Lookup(".hash", 0))
-
-		elfwritedynentsym(ctxt, s, DT_SYMTAB, ctxt.Syms.Lookup(".dynsym", 0))
-		if elf64 {
-			Elfwritedynent(ctxt, s, DT_SYMENT, ELF64SYMSIZE)
-		} else {
-			Elfwritedynent(ctxt, s, DT_SYMENT, ELF32SYMSIZE)
-		}
-		elfwritedynentsym(ctxt, s, DT_STRTAB, ctxt.Syms.Lookup(".dynstr", 0))
-		elfwritedynentsymsize(ctxt, s, DT_STRSZ, ctxt.Syms.Lookup(".dynstr", 0))
-		if elfRelType == ".rela" {
-			elfwritedynentsym(ctxt, s, DT_RELA, ctxt.Syms.Lookup(".rela", 0))
-			elfwritedynentsymsize(ctxt, s, DT_RELASZ, ctxt.Syms.Lookup(".rela", 0))
-			Elfwritedynent(ctxt, s, DT_RELAENT, ELF64RELASIZE)
-		} else {
-			elfwritedynentsym(ctxt, s, DT_REL, ctxt.Syms.Lookup(".rel", 0))
-			elfwritedynentsymsize(ctxt, s, DT_RELSZ, ctxt.Syms.Lookup(".rel", 0))
-			Elfwritedynent(ctxt, s, DT_RELENT, ELF32RELSIZE)
-		}
-
-		if rpath.val != "" {
-			Elfwritedynent(ctxt, s, DT_RUNPATH, uint64(Addstring(dynstr, rpath.val)))
-		}
-
-		if ctxt.Arch.Family == sys.PPC64 {
-			elfwritedynentsym(ctxt, s, DT_PLTGOT, ctxt.Syms.Lookup(".plt", 0))
-		} else if ctxt.Arch.Family == sys.S390X {
-			elfwritedynentsym(ctxt, s, DT_PLTGOT, ctxt.Syms.Lookup(".got", 0))
-		} else {
-			elfwritedynentsym(ctxt, s, DT_PLTGOT, ctxt.Syms.Lookup(".got.plt", 0))
-		}
-
-		if ctxt.Arch.Family == sys.PPC64 {
-			Elfwritedynent(ctxt, s, DT_PPC64_OPT, 0)
-		}
-
-		// Solaris dynamic linker can't handle an empty .rela.plt if
-		// DT_JMPREL is emitted so we have to defer generation of DT_PLTREL,
-		// DT_PLTRELSZ, and DT_JMPREL dynamic entries until after we know the
-		// size of .rel(a).plt section.
-		Elfwritedynent(ctxt, s, DT_DEBUG, 0)
-	}
-
-	if ctxt.BuildMode == BuildModeShared {
-		// The go.link.abihashbytes symbol will be pointed at the appropriate
-		// part of the .note.go.abihash section in data.go:func address().
-		s := ctxt.Syms.Lookup("go.link.abihashbytes", 0)
-		s.Attr |= sym.AttrLocal
-		s.Type = sym.SRODATA
-		s.Attr |= sym.AttrSpecial
-		s.Attr |= sym.AttrReachable
-		s.Size = int64(sha1.Size)
-
-		sort.Sort(byPkg(ctxt.Library))
-		h := sha1.New()
-		for _, l := range ctxt.Library {
-			io.WriteString(h, l.Hash)
-		}
-		addgonote(ctxt, ".note.go.abihash", ELF_NOTE_GOABIHASH_TAG, h.Sum([]byte{}))
-		addgonote(ctxt, ".note.go.pkg-list", ELF_NOTE_GOPKGLIST_TAG, pkglistfornote)
-		var deplist []string
-		for _, shlib := range ctxt.Shlibs {
-			deplist = append(deplist, filepath.Base(shlib.Path))
-		}
-		addgonote(ctxt, ".note.go.deps", ELF_NOTE_GODEPS_TAG, []byte(strings.Join(deplist, "\n")))
-	}
-
-	if ctxt.LinkMode == LinkExternal && *flagBuildid != "" {
-		addgonote(ctxt, ".note.go.buildid", ELF_NOTE_GOBUILDID_TAG, []byte(*flagBuildid))
-	}
-}
-
-// Do not write DT_NULL.  elfdynhash will finish it.
-func shsym(sh *ElfShdr, s *sym.Symbol) {
-	addr := Symaddr(s)
-	if sh.flags&SHF_ALLOC != 0 {
-		sh.addr = uint64(addr)
-	}
-	sh.off = uint64(datoff(s, addr))
-	sh.size = uint64(s.Size)
-}
-
-func phsh(ph *ElfPhdr, sh *ElfShdr) {
-	ph.vaddr = sh.addr
-	ph.paddr = ph.vaddr
-	ph.off = sh.off
-	ph.filesz = sh.size
-	ph.memsz = sh.size
-	ph.align = sh.addralign
-}
-
-func Asmbelfsetup() {
-	/* This null SHdr must appear before all others */
-	elfshname("")
-
-	for _, sect := range Segtext.Sections {
-		// There could be multiple .text sections. Instead check the Elfsect
-		// field to determine if already has an ElfShdr and if not, create one.
-		if sect.Name == ".text" {
-			if sect.Elfsect == nil {
-				sect.Elfsect = elfshnamedup(sect.Name)
-			}
-		} else {
-			elfshalloc(sect)
-		}
-	}
-	for _, sect := range Segrodata.Sections {
-		elfshalloc(sect)
-	}
-	for _, sect := range Segrelrodata.Sections {
-		elfshalloc(sect)
-	}
-	for _, sect := range Segdata.Sections {
-		elfshalloc(sect)
-	}
-	for _, sect := range Segdwarf.Sections {
-		elfshalloc(sect)
-	}
-}
-
-func Asmbelf(ctxt *Link, symo int64) {
-	eh := getElfEhdr()
-	switch ctxt.Arch.Family {
-	default:
-		Exitf("unknown architecture in asmbelf: %v", ctxt.Arch.Family)
-	case sys.MIPS, sys.MIPS64:
-		eh.machine = EM_MIPS
-	case sys.ARM:
-		eh.machine = EM_ARM
-	case sys.AMD64:
-		eh.machine = EM_X86_64
-	case sys.ARM64:
-		eh.machine = EM_AARCH64
-	case sys.I386:
-		eh.machine = EM_386
-	case sys.PPC64:
-		eh.machine = EM_PPC64
-	case sys.RISCV64:
-		eh.machine = EM_RISCV
-	case sys.S390X:
-		eh.machine = EM_S390
-	}
-
-	elfreserve := int64(ELFRESERVE)
-
-	numtext := int64(0)
-	for _, sect := range Segtext.Sections {
-		if sect.Name == ".text" {
-			numtext++
-		}
-	}
-
-	// If there are multiple text sections, extra space is needed
-	// in the elfreserve for the additional .text and .rela.text
-	// section headers.  It can handle 4 extra now. Headers are
-	// 64 bytes.
-
-	if numtext > 4 {
-		elfreserve += elfreserve + numtext*64*2
-	}
-
-	startva := *FlagTextAddr - int64(HEADR)
-	resoff := elfreserve
-
-	var pph *ElfPhdr
-	var pnote *ElfPhdr
-	if *flagRace && ctxt.HeadType == objabi.Hnetbsd {
-		sh := elfshname(".note.netbsd.pax")
-		resoff -= int64(elfnetbsdpax(sh, uint64(startva), uint64(resoff)))
-		pnote = newElfPhdr()
-		pnote.type_ = PT_NOTE
-		pnote.flags = PF_R
-		phsh(pnote, sh)
-	}
-	if ctxt.LinkMode == LinkExternal {
-		/* skip program headers */
-		eh.phoff = 0
-
-		eh.phentsize = 0
-
-		if ctxt.BuildMode == BuildModeShared {
-			sh := elfshname(".note.go.pkg-list")
-			sh.type_ = SHT_NOTE
-			sh = elfshname(".note.go.abihash")
-			sh.type_ = SHT_NOTE
-			sh.flags = SHF_ALLOC
-			sh = elfshname(".note.go.deps")
-			sh.type_ = SHT_NOTE
-		}
-
-		if *flagBuildid != "" {
-			sh := elfshname(".note.go.buildid")
-			sh.type_ = SHT_NOTE
-			sh.flags = SHF_ALLOC
-		}
-
-		goto elfobj
-	}
-
-	/* program header info */
-	pph = newElfPhdr()
-
-	pph.type_ = PT_PHDR
-	pph.flags = PF_R
-	pph.off = uint64(eh.ehsize)
-	pph.vaddr = uint64(*FlagTextAddr) - uint64(HEADR) + pph.off
-	pph.paddr = uint64(*FlagTextAddr) - uint64(HEADR) + pph.off
-	pph.align = uint64(*FlagRound)
-
-	/*
-	 * PHDR must be in a loaded segment. Adjust the text
-	 * segment boundaries downwards to include it.
-	 */
-	{
-		o := int64(Segtext.Vaddr - pph.vaddr)
-		Segtext.Vaddr -= uint64(o)
-		Segtext.Length += uint64(o)
-		o = int64(Segtext.Fileoff - pph.off)
-		Segtext.Fileoff -= uint64(o)
-		Segtext.Filelen += uint64(o)
-	}
-
-	if !*FlagD { /* -d suppresses dynamic loader format */
-		/* interpreter */
-		sh := elfshname(".interp")
-
-		sh.type_ = SHT_PROGBITS
-		sh.flags = SHF_ALLOC
-		sh.addralign = 1
-
-		if interpreter == "" && objabi.GO_LDSO != "" {
-			interpreter = objabi.GO_LDSO
-		}
-
-		if interpreter == "" {
-			switch ctxt.HeadType {
-			case objabi.Hlinux:
-				if objabi.GOOS == "android" {
-					interpreter = thearch.Androiddynld
-					if interpreter == "" {
-						Exitf("ELF interpreter not set")
-					}
-				} else {
-					interpreter = thearch.Linuxdynld
-				}
-
-			case objabi.Hfreebsd:
-				interpreter = thearch.Freebsddynld
-
-			case objabi.Hnetbsd:
-				interpreter = thearch.Netbsddynld
-
-			case objabi.Hopenbsd:
-				interpreter = thearch.Openbsddynld
-
-			case objabi.Hdragonfly:
-				interpreter = thearch.Dragonflydynld
-
-			case objabi.Hsolaris:
-				interpreter = thearch.Solarisdynld
-			}
-		}
-
-		resoff -= int64(elfinterp(sh, uint64(startva), uint64(resoff), interpreter))
-
-		ph := newElfPhdr()
-		ph.type_ = PT_INTERP
-		ph.flags = PF_R
-		phsh(ph, sh)
-	}
-
-	pnote = nil
-	if ctxt.HeadType == objabi.Hnetbsd || ctxt.HeadType == objabi.Hopenbsd {
-		var sh *ElfShdr
-		switch ctxt.HeadType {
-		case objabi.Hnetbsd:
-			sh = elfshname(".note.netbsd.ident")
-			resoff -= int64(elfnetbsdsig(sh, uint64(startva), uint64(resoff)))
-
-		case objabi.Hopenbsd:
-			sh = elfshname(".note.openbsd.ident")
-			resoff -= int64(elfopenbsdsig(sh, uint64(startva), uint64(resoff)))
-		}
-
-		pnote = newElfPhdr()
-		pnote.type_ = PT_NOTE
-		pnote.flags = PF_R
-		phsh(pnote, sh)
-	}
-
-	if len(buildinfo) > 0 {
-		sh := elfshname(".note.gnu.build-id")
-		resoff -= int64(elfbuildinfo(sh, uint64(startva), uint64(resoff)))
-
-		if pnote == nil {
-			pnote = newElfPhdr()
-			pnote.type_ = PT_NOTE
-			pnote.flags = PF_R
-		}
-
-		phsh(pnote, sh)
-	}
-
-	if *flagBuildid != "" {
-		sh := elfshname(".note.go.buildid")
-		resoff -= int64(elfgobuildid(sh, uint64(startva), uint64(resoff)))
-
-		pnote := newElfPhdr()
-		pnote.type_ = PT_NOTE
-		pnote.flags = PF_R
-		phsh(pnote, sh)
-	}
-
-	// Additions to the reserved area must be above this line.
-
-	elfphload(&Segtext)
-	if len(Segrodata.Sections) > 0 {
-		elfphload(&Segrodata)
-	}
-	if len(Segrelrodata.Sections) > 0 {
-		elfphload(&Segrelrodata)
-		elfphrelro(&Segrelrodata)
-	}
-	elfphload(&Segdata)
-
-	/* Dynamic linking sections */
-	if !*FlagD {
-		sh := elfshname(".dynsym")
-		sh.type_ = SHT_DYNSYM
-		sh.flags = SHF_ALLOC
-		if elf64 {
-			sh.entsize = ELF64SYMSIZE
-		} else {
-			sh.entsize = ELF32SYMSIZE
-		}
-		sh.addralign = uint64(ctxt.Arch.RegSize)
-		sh.link = uint32(elfshname(".dynstr").shnum)
-
-		// sh.info is the index of first non-local symbol (number of local symbols)
-		s := ctxt.Syms.Lookup(".dynsym", 0)
-		i := uint32(0)
-		for sub := s; sub != nil; sub = sub.Sub {
-			i++
-			if !sub.Attr.Local() {
-				break
-			}
-		}
-		sh.info = i
-		shsym(sh, s)
-
-		sh = elfshname(".dynstr")
-		sh.type_ = SHT_STRTAB
-		sh.flags = SHF_ALLOC
-		sh.addralign = 1
-		shsym(sh, ctxt.Syms.Lookup(".dynstr", 0))
-
-		if elfverneed != 0 {
-			sh := elfshname(".gnu.version")
-			sh.type_ = SHT_GNU_VERSYM
-			sh.flags = SHF_ALLOC
-			sh.addralign = 2
-			sh.link = uint32(elfshname(".dynsym").shnum)
-			sh.entsize = 2
-			shsym(sh, ctxt.Syms.Lookup(".gnu.version", 0))
-
-			sh = elfshname(".gnu.version_r")
-			sh.type_ = SHT_GNU_VERNEED
-			sh.flags = SHF_ALLOC
-			sh.addralign = uint64(ctxt.Arch.RegSize)
-			sh.info = uint32(elfverneed)
-			sh.link = uint32(elfshname(".dynstr").shnum)
-			shsym(sh, ctxt.Syms.Lookup(".gnu.version_r", 0))
-		}
-
-		if elfRelType == ".rela" {
-			sh := elfshname(".rela.plt")
-			sh.type_ = SHT_RELA
-			sh.flags = SHF_ALLOC
-			sh.entsize = ELF64RELASIZE
-			sh.addralign = uint64(ctxt.Arch.RegSize)
-			sh.link = uint32(elfshname(".dynsym").shnum)
-			sh.info = uint32(elfshname(".plt").shnum)
-			shsym(sh, ctxt.Syms.Lookup(".rela.plt", 0))
-
-			sh = elfshname(".rela")
-			sh.type_ = SHT_RELA
-			sh.flags = SHF_ALLOC
-			sh.entsize = ELF64RELASIZE
-			sh.addralign = 8
-			sh.link = uint32(elfshname(".dynsym").shnum)
-			shsym(sh, ctxt.Syms.Lookup(".rela", 0))
-		} else {
-			sh := elfshname(".rel.plt")
-			sh.type_ = SHT_REL
-			sh.flags = SHF_ALLOC
-			sh.entsize = ELF32RELSIZE
-			sh.addralign = 4
-			sh.link = uint32(elfshname(".dynsym").shnum)
-			shsym(sh, ctxt.Syms.Lookup(".rel.plt", 0))
-
-			sh = elfshname(".rel")
-			sh.type_ = SHT_REL
-			sh.flags = SHF_ALLOC
-			sh.entsize = ELF32RELSIZE
-			sh.addralign = 4
-			sh.link = uint32(elfshname(".dynsym").shnum)
-			shsym(sh, ctxt.Syms.Lookup(".rel", 0))
-		}
-
-		if eh.machine == EM_PPC64 {
-			sh := elfshname(".glink")
-			sh.type_ = SHT_PROGBITS
-			sh.flags = SHF_ALLOC + SHF_EXECINSTR
-			sh.addralign = 4
-			shsym(sh, ctxt.Syms.Lookup(".glink", 0))
-		}
-
-		sh = elfshname(".plt")
-		sh.type_ = SHT_PROGBITS
-		sh.flags = SHF_ALLOC + SHF_EXECINSTR
-		if eh.machine == EM_X86_64 {
-			sh.entsize = 16
-		} else if eh.machine == EM_S390 {
-			sh.entsize = 32
-		} else if eh.machine == EM_PPC64 {
-			// On ppc64, this is just a table of addresses
-			// filled by the dynamic linker
-			sh.type_ = SHT_NOBITS
-
-			sh.flags = SHF_ALLOC + SHF_WRITE
-			sh.entsize = 8
-		} else {
-			sh.entsize = 4
-		}
-		sh.addralign = sh.entsize
-		shsym(sh, ctxt.Syms.Lookup(".plt", 0))
-
-		// On ppc64, .got comes from the input files, so don't
-		// create it here, and .got.plt is not used.
-		if eh.machine != EM_PPC64 {
-			sh := elfshname(".got")
-			sh.type_ = SHT_PROGBITS
-			sh.flags = SHF_ALLOC + SHF_WRITE
-			sh.entsize = uint64(ctxt.Arch.RegSize)
-			sh.addralign = uint64(ctxt.Arch.RegSize)
-			shsym(sh, ctxt.Syms.Lookup(".got", 0))
-
-			sh = elfshname(".got.plt")
-			sh.type_ = SHT_PROGBITS
-			sh.flags = SHF_ALLOC + SHF_WRITE
-			sh.entsize = uint64(ctxt.Arch.RegSize)
-			sh.addralign = uint64(ctxt.Arch.RegSize)
-			shsym(sh, ctxt.Syms.Lookup(".got.plt", 0))
-		}
-
-		sh = elfshname(".hash")
-		sh.type_ = SHT_HASH
-		sh.flags = SHF_ALLOC
-		sh.entsize = 4
-		sh.addralign = uint64(ctxt.Arch.RegSize)
-		sh.link = uint32(elfshname(".dynsym").shnum)
-		shsym(sh, ctxt.Syms.Lookup(".hash", 0))
-
-		/* sh and PT_DYNAMIC for .dynamic section */
-		sh = elfshname(".dynamic")
-
-		sh.type_ = SHT_DYNAMIC
-		sh.flags = SHF_ALLOC + SHF_WRITE
-		sh.entsize = 2 * uint64(ctxt.Arch.RegSize)
-		sh.addralign = uint64(ctxt.Arch.RegSize)
-		sh.link = uint32(elfshname(".dynstr").shnum)
-		shsym(sh, ctxt.Syms.Lookup(".dynamic", 0))
-		ph := newElfPhdr()
-		ph.type_ = PT_DYNAMIC
-		ph.flags = PF_R + PF_W
-		phsh(ph, sh)
-
-		/*
-		 * Thread-local storage segment (really just size).
-		 */
-		tlssize := uint64(0)
-		for _, sect := range Segdata.Sections {
-			if sect.Name == ".tbss" {
-				tlssize = sect.Length
-			}
-		}
-		if tlssize != 0 {
-			ph := newElfPhdr()
-			ph.type_ = PT_TLS
-			ph.flags = PF_R
-			ph.memsz = tlssize
-			ph.align = uint64(ctxt.Arch.RegSize)
-		}
-	}
-
-	if ctxt.HeadType == objabi.Hlinux {
-		ph := newElfPhdr()
-		ph.type_ = PT_GNU_STACK
-		ph.flags = PF_W + PF_R
-		ph.align = uint64(ctxt.Arch.RegSize)
-
-		ph = newElfPhdr()
-		ph.type_ = PT_PAX_FLAGS
-		ph.flags = 0x2a00 // mprotect, randexec, emutramp disabled
-		ph.align = uint64(ctxt.Arch.RegSize)
-	} else if ctxt.HeadType == objabi.Hsolaris {
-		ph := newElfPhdr()
-		ph.type_ = PT_SUNWSTACK
-		ph.flags = PF_W + PF_R
-	}
-
-elfobj:
-	sh := elfshname(".shstrtab")
-	sh.type_ = SHT_STRTAB
-	sh.addralign = 1
-	shsym(sh, ctxt.Syms.Lookup(".shstrtab", 0))
-	eh.shstrndx = uint16(sh.shnum)
-
-	// put these sections early in the list
-	if !*FlagS {
-		elfshname(".symtab")
-		elfshname(".strtab")
-	}
-
-	for _, sect := range Segtext.Sections {
-		elfshbits(ctxt.LinkMode, sect)
-	}
-	for _, sect := range Segrodata.Sections {
-		elfshbits(ctxt.LinkMode, sect)
-	}
-	for _, sect := range Segrelrodata.Sections {
-		elfshbits(ctxt.LinkMode, sect)
-	}
-	for _, sect := range Segdata.Sections {
-		elfshbits(ctxt.LinkMode, sect)
-	}
-	for _, sect := range Segdwarf.Sections {
-		elfshbits(ctxt.LinkMode, sect)
-	}
-
-	if ctxt.LinkMode == LinkExternal {
-		for _, sect := range Segtext.Sections {
-			elfshreloc(ctxt.Arch, sect)
-		}
-		for _, sect := range Segrodata.Sections {
-			elfshreloc(ctxt.Arch, sect)
-		}
-		for _, sect := range Segrelrodata.Sections {
-			elfshreloc(ctxt.Arch, sect)
-		}
-		for _, sect := range Segdata.Sections {
-			elfshreloc(ctxt.Arch, sect)
-		}
-		for _, s := range dwarfp {
-			if len(s.R) > 0 || s.Type == sym.SDWARFINFO || s.Type == sym.SDWARFLOC {
-				elfshreloc(ctxt.Arch, s.Sect)
-			}
-		}
-		// add a .note.GNU-stack section to mark the stack as non-executable
-		sh := elfshname(".note.GNU-stack")
-
-		sh.type_ = SHT_PROGBITS
-		sh.addralign = 1
-		sh.flags = 0
-	}
-
-	if !*FlagS {
-		sh := elfshname(".symtab")
-		sh.type_ = SHT_SYMTAB
-		sh.off = uint64(symo)
-		sh.size = uint64(Symsize)
-		sh.addralign = uint64(ctxt.Arch.RegSize)
-		sh.entsize = 8 + 2*uint64(ctxt.Arch.RegSize)
-		sh.link = uint32(elfshname(".strtab").shnum)
-		sh.info = uint32(elfglobalsymndx)
-
-		sh = elfshname(".strtab")
-		sh.type_ = SHT_STRTAB
-		sh.off = uint64(symo) + uint64(Symsize)
-		sh.size = uint64(len(Elfstrdat))
-		sh.addralign = 1
-	}
-
-	/* Main header */
-	eh.ident[EI_MAG0] = '\177'
-
-	eh.ident[EI_MAG1] = 'E'
-	eh.ident[EI_MAG2] = 'L'
-	eh.ident[EI_MAG3] = 'F'
-	if ctxt.HeadType == objabi.Hfreebsd {
-		eh.ident[EI_OSABI] = ELFOSABI_FREEBSD
-	} else if ctxt.HeadType == objabi.Hnetbsd {
-		eh.ident[EI_OSABI] = ELFOSABI_NETBSD
-	} else if ctxt.HeadType == objabi.Hopenbsd {
-		eh.ident[EI_OSABI] = ELFOSABI_OPENBSD
-	} else if ctxt.HeadType == objabi.Hdragonfly {
-		eh.ident[EI_OSABI] = ELFOSABI_NONE
-	}
-	if elf64 {
-		eh.ident[EI_CLASS] = ELFCLASS64
-	} else {
-		eh.ident[EI_CLASS] = ELFCLASS32
-	}
-	if ctxt.Arch.ByteOrder == binary.BigEndian {
-		eh.ident[EI_DATA] = ELFDATA2MSB
-	} else {
-		eh.ident[EI_DATA] = ELFDATA2LSB
-	}
-	eh.ident[EI_VERSION] = EV_CURRENT
-
-	if ctxt.LinkMode == LinkExternal {
-		eh.type_ = ET_REL
-	} else if ctxt.BuildMode == BuildModePIE {
-		eh.type_ = ET_DYN
-	} else {
-		eh.type_ = ET_EXEC
-	}
-
-	if ctxt.LinkMode != LinkExternal {
-		eh.entry = uint64(Entryvalue(ctxt))
-	}
-
-	eh.version = EV_CURRENT
-
-	if pph != nil {
-		pph.filesz = uint64(eh.phnum) * uint64(eh.phentsize)
-		pph.memsz = pph.filesz
-	}
-
-	ctxt.Out.SeekSet(0)
-	a := int64(0)
-	a += int64(elfwritehdr(ctxt.Out))
-	a += int64(elfwritephdrs(ctxt.Out))
-	a += int64(elfwriteshdrs(ctxt.Out))
-	if !*FlagD {
-		a += int64(elfwriteinterp(ctxt.Out))
-	}
-	if ctxt.LinkMode != LinkExternal {
-		if ctxt.HeadType == objabi.Hnetbsd {
-			a += int64(elfwritenetbsdsig(ctxt.Out))
-		}
-		if ctxt.HeadType == objabi.Hopenbsd {
-			a += int64(elfwriteopenbsdsig(ctxt.Out))
-		}
-		if len(buildinfo) > 0 {
-			a += int64(elfwritebuildinfo(ctxt.Out))
-		}
-		if *flagBuildid != "" {
-			a += int64(elfwritegobuildid(ctxt.Out))
-		}
-	}
-	if *flagRace && ctxt.HeadType == objabi.Hnetbsd {
-		a += int64(elfwritenetbsdpax(ctxt.Out))
-	}
-
-	if a > elfreserve {
-		Errorf(nil, "ELFRESERVE too small: %d > %d with %d text sections", a, elfreserve, numtext)
-	}
-}
-
-func elfadddynsym(ctxt *Link, s *sym.Symbol) {
-	if elf64 {
-		s.Dynid = int32(Nelfsym)
-		Nelfsym++
-
-		d := ctxt.Syms.Lookup(".dynsym", 0)
-
-		name := s.Extname()
-		d.AddUint32(ctxt.Arch, uint32(Addstring(ctxt.Syms.Lookup(".dynstr", 0), name)))
-
-		/* type */
-		t := STB_GLOBAL << 4
-
-		if s.Attr.CgoExport() && s.Type == sym.STEXT {
-			t |= STT_FUNC
-		} else {
-			t |= STT_OBJECT
-		}
-		d.AddUint8(uint8(t))
-
-		/* reserved */
-		d.AddUint8(0)
-
-		/* section where symbol is defined */
-		if s.Type == sym.SDYNIMPORT {
-			d.AddUint16(ctxt.Arch, SHN_UNDEF)
-		} else {
-			d.AddUint16(ctxt.Arch, 1)
-		}
-
-		/* value */
-		if s.Type == sym.SDYNIMPORT {
-			d.AddUint64(ctxt.Arch, 0)
-		} else {
-			d.AddAddr(ctxt.Arch, s)
-		}
-
-		/* size of object */
-		d.AddUint64(ctxt.Arch, uint64(s.Size))
-
-		if ctxt.Arch.Family == sys.AMD64 && !s.Attr.CgoExportDynamic() && s.Dynimplib() != "" && !seenlib[s.Dynimplib()] {
-			Elfwritedynent(ctxt, ctxt.Syms.Lookup(".dynamic", 0), DT_NEEDED, uint64(Addstring(ctxt.Syms.Lookup(".dynstr", 0), s.Dynimplib())))
-		}
-	} else {
-		s.Dynid = int32(Nelfsym)
-		Nelfsym++
-
-		d := ctxt.Syms.Lookup(".dynsym", 0)
-
-		/* name */
-		name := s.Extname()
-
-		d.AddUint32(ctxt.Arch, uint32(Addstring(ctxt.Syms.Lookup(".dynstr", 0), name)))
-
-		/* value */
-		if s.Type == sym.SDYNIMPORT {
-			d.AddUint32(ctxt.Arch, 0)
-		} else {
-			d.AddAddr(ctxt.Arch, s)
-		}
-
-		/* size of object */
-		d.AddUint32(ctxt.Arch, uint32(s.Size))
-
-		/* type */
-		t := STB_GLOBAL << 4
-
-		// TODO(mwhudson): presumably the behavior should actually be the same on both arm and 386.
-		if ctxt.Arch.Family == sys.I386 && s.Attr.CgoExport() && s.Type == sym.STEXT {
-			t |= STT_FUNC
-		} else if ctxt.Arch.Family == sys.ARM && s.Attr.CgoExportDynamic() && s.Type == sym.STEXT {
-			t |= STT_FUNC
-		} else {
-			t |= STT_OBJECT
-		}
-		d.AddUint8(uint8(t))
-		d.AddUint8(0)
-
-		/* shndx */
-		if s.Type == sym.SDYNIMPORT {
-			d.AddUint16(ctxt.Arch, SHN_UNDEF)
-		} else {
-			d.AddUint16(ctxt.Arch, 1)
-		}
-	}
-}
-
-func ELF32_R_SYM(info uint32) uint32 {
-	return info >> 8
-}
-
-func ELF32_R_TYPE(info uint32) uint32 {
-	return uint32(uint8(info))
-}
-
-func ELF32_R_INFO(sym uint32, type_ uint32) uint32 {
-	return sym<<8 | type_
-}
-
-func ELF32_ST_BIND(info uint8) uint8 {
-	return info >> 4
-}
-
-func ELF32_ST_TYPE(info uint8) uint8 {
-	return info & 0xf
-}
-
-func ELF32_ST_INFO(bind uint8, type_ uint8) uint8 {
-	return bind<<4 | type_&0xf
-}
-
-func ELF32_ST_VISIBILITY(oth uint8) uint8 {
-	return oth & 3
-}
-
-func ELF64_R_SYM(info uint64) uint32 {
-	return uint32(info >> 32)
-}
-
-func ELF64_R_TYPE(info uint64) uint32 {
-	return uint32(info)
-}
-
-func ELF64_R_INFO(sym uint32, type_ uint32) uint64 {
-	return uint64(sym)<<32 | uint64(type_)
-}
-
-func ELF64_ST_BIND(info uint8) uint8 {
-	return info >> 4
-}
-
-func ELF64_ST_TYPE(info uint8) uint8 {
-	return info & 0xf
-}
-
-func ELF64_ST_INFO(bind uint8, type_ uint8) uint8 {
-	return bind<<4 | type_&0xf
-}
-
-func ELF64_ST_VISIBILITY(oth uint8) uint8 {
-	return oth & 3
-}
diff --git a/src/cmd/oldlink/internal/ld/execarchive.go b/src/cmd/oldlink/internal/ld/execarchive.go
deleted file mode 100644
index fe5cc40..0000000
--- a/src/cmd/oldlink/internal/ld/execarchive.go
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright 2019 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.
-
-// +build !wasm,!windows
-
-package ld
-
-import (
-	"os"
-	"os/exec"
-	"path/filepath"
-	"syscall"
-)
-
-const syscallExecSupported = true
-
-// execArchive invokes the archiver tool with syscall.Exec(), with
-// the expectation that this is the last thing that takes place
-// in the linking operation.
-func (ctxt *Link) execArchive(argv []string) {
-	var err error
-	argv0 := argv[0]
-	if filepath.Base(argv0) == argv0 {
-		argv0, err = exec.LookPath(argv0)
-		if err != nil {
-			Exitf("cannot find %s: %v", argv[0], err)
-		}
-	}
-	if ctxt.Debugvlog != 0 {
-		ctxt.Logf("invoking archiver with syscall.Exec()\n")
-	}
-	err = syscall.Exec(argv0, argv, os.Environ())
-	if err != nil {
-		Exitf("running %s failed: %v", argv[0], err)
-	}
-}
diff --git a/src/cmd/oldlink/internal/ld/execarchive_noexec.go b/src/cmd/oldlink/internal/ld/execarchive_noexec.go
deleted file mode 100644
index a70dea9..0000000
--- a/src/cmd/oldlink/internal/ld/execarchive_noexec.go
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright 2019 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.
-
-// +build wasm windows
-
-package ld
-
-const syscallExecSupported = false
-
-func (ctxt *Link) execArchive(argv []string) {
-	panic("should never arrive here")
-}
diff --git a/src/cmd/oldlink/internal/ld/go.go b/src/cmd/oldlink/internal/ld/go.go
deleted file mode 100644
index b052655..0000000
--- a/src/cmd/oldlink/internal/ld/go.go
+++ /dev/null
@@ -1,442 +0,0 @@
-// Copyright 2009 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.
-
-// go-specific code shared across loaders (5l, 6l, 8l).
-
-package ld
-
-import (
-	"bytes"
-	"cmd/internal/bio"
-	"cmd/internal/objabi"
-	"cmd/oldlink/internal/sym"
-	"encoding/json"
-	"fmt"
-	"io"
-	"os"
-	"strings"
-)
-
-// go-specific code shared across loaders (5l, 6l, 8l).
-
-// replace all "". with pkg.
-func expandpkg(t0 string, pkg string) string {
-	return strings.Replace(t0, `"".`, pkg+".", -1)
-}
-
-func resolveABIAlias(s *sym.Symbol) *sym.Symbol {
-	if s.Type != sym.SABIALIAS {
-		return s
-	}
-	target := s.R[0].Sym
-	if target.Type == sym.SABIALIAS {
-		panic(fmt.Sprintf("ABI alias %s references another ABI alias %s", s, target))
-	}
-	return target
-}
-
-// TODO:
-//	generate debugging section in binary.
-//	once the dust settles, try to move some code to
-//		libmach, so that other linkers and ar can share.
-
-func ldpkg(ctxt *Link, f *bio.Reader, lib *sym.Library, length int64, filename string) {
-	if *flagG {
-		return
-	}
-
-	if int64(int(length)) != length {
-		fmt.Fprintf(os.Stderr, "%s: too much pkg data in %s\n", os.Args[0], filename)
-		if *flagU {
-			errorexit()
-		}
-		return
-	}
-
-	bdata := make([]byte, length)
-	if _, err := io.ReadFull(f, bdata); err != nil {
-		fmt.Fprintf(os.Stderr, "%s: short pkg read %s\n", os.Args[0], filename)
-		if *flagU {
-			errorexit()
-		}
-		return
-	}
-	data := string(bdata)
-
-	// process header lines
-	for data != "" {
-		var line string
-		if i := strings.Index(data, "\n"); i >= 0 {
-			line, data = data[:i], data[i+1:]
-		} else {
-			line, data = data, ""
-		}
-		if line == "safe" {
-			lib.Safe = true
-		}
-		if line == "main" {
-			lib.Main = true
-		}
-		if line == "" {
-			break
-		}
-	}
-
-	// look for cgo section
-	p0 := strings.Index(data, "\n$$  // cgo")
-	var p1 int
-	if p0 >= 0 {
-		p0 += p1
-		i := strings.IndexByte(data[p0+1:], '\n')
-		if i < 0 {
-			fmt.Fprintf(os.Stderr, "%s: found $$ // cgo but no newline in %s\n", os.Args[0], filename)
-			if *flagU {
-				errorexit()
-			}
-			return
-		}
-		p0 += 1 + i
-
-		p1 = strings.Index(data[p0:], "\n$$")
-		if p1 < 0 {
-			p1 = strings.Index(data[p0:], "\n!\n")
-		}
-		if p1 < 0 {
-			fmt.Fprintf(os.Stderr, "%s: cannot find end of // cgo section in %s\n", os.Args[0], filename)
-			if *flagU {
-				errorexit()
-			}
-			return
-		}
-		p1 += p0
-		loadcgo(ctxt, filename, objabi.PathToPrefix(lib.Pkg), data[p0:p1])
-	}
-}
-
-func loadcgo(ctxt *Link, file string, pkg string, p string) {
-	var directives [][]string
-	if err := json.NewDecoder(strings.NewReader(p)).Decode(&directives); err != nil {
-		fmt.Fprintf(os.Stderr, "%s: %s: failed decoding cgo directives: %v\n", os.Args[0], file, err)
-		nerrors++
-		return
-	}
-
-	// Find cgo_export symbols. They are roots in the deadcode pass.
-	for _, f := range directives {
-		switch f[0] {
-		case "cgo_export_static", "cgo_export_dynamic":
-			if len(f) < 2 || len(f) > 3 {
-				continue
-			}
-			local := f[1]
-			switch ctxt.BuildMode {
-			case BuildModeCShared, BuildModeCArchive, BuildModePlugin:
-				if local == "main" {
-					continue
-				}
-			}
-			local = expandpkg(local, pkg)
-			if f[0] == "cgo_export_static" {
-				ctxt.cgo_export_static[local] = true
-			} else {
-				ctxt.cgo_export_dynamic[local] = true
-			}
-		}
-	}
-
-	if *flagNewobj {
-		// Record the directives. We'll process them later after Symbols are created.
-		ctxt.cgodata = append(ctxt.cgodata, cgodata{file, pkg, directives})
-	} else {
-		setCgoAttr(ctxt, ctxt.Syms.Lookup, file, pkg, directives)
-	}
-}
-
-// Set symbol attributes or flags based on cgo directives.
-func setCgoAttr(ctxt *Link, lookup func(string, int) *sym.Symbol, file string, pkg string, directives [][]string) {
-	for _, f := range directives {
-		switch f[0] {
-		case "cgo_import_dynamic":
-			if len(f) < 2 || len(f) > 4 {
-				break
-			}
-
-			local := f[1]
-			remote := local
-			if len(f) > 2 {
-				remote = f[2]
-			}
-			lib := ""
-			if len(f) > 3 {
-				lib = f[3]
-			}
-
-			if *FlagD {
-				fmt.Fprintf(os.Stderr, "%s: %s: cannot use dynamic imports with -d flag\n", os.Args[0], file)
-				nerrors++
-				return
-			}
-
-			if local == "_" && remote == "_" {
-				// allow #pragma dynimport _ _ "foo.so"
-				// to force a link of foo.so.
-				havedynamic = 1
-
-				if ctxt.HeadType == objabi.Hdarwin {
-					machoadddynlib(lib, ctxt.LinkMode)
-				} else {
-					dynlib = append(dynlib, lib)
-				}
-				continue
-			}
-
-			local = expandpkg(local, pkg)
-			q := ""
-			if i := strings.Index(remote, "#"); i >= 0 {
-				remote, q = remote[:i], remote[i+1:]
-			}
-			s := lookup(local, 0)
-			if s.Type == 0 || s.Type == sym.SXREF || s.Type == sym.SBSS || s.Type == sym.SNOPTRBSS || s.Type == sym.SHOSTOBJ {
-				s.SetDynimplib(lib)
-				s.SetExtname(remote)
-				s.SetDynimpvers(q)
-				if s.Type != sym.SHOSTOBJ {
-					s.Type = sym.SDYNIMPORT
-				}
-				havedynamic = 1
-			}
-
-			continue
-
-		case "cgo_import_static":
-			if len(f) != 2 {
-				break
-			}
-			local := f[1]
-
-			s := lookup(local, 0)
-			s.Type = sym.SHOSTOBJ
-			s.Size = 0
-			continue
-
-		case "cgo_export_static", "cgo_export_dynamic":
-			if len(f) < 2 || len(f) > 3 {
-				break
-			}
-			local := f[1]
-			remote := local
-			if len(f) > 2 {
-				remote = f[2]
-			}
-			local = expandpkg(local, pkg)
-
-			// The compiler arranges for an ABI0 wrapper
-			// to be available for all cgo-exported
-			// functions. Link.loadlib will resolve any
-			// ABI aliases we find here (since we may not
-			// yet know it's an alias).
-			s := lookup(local, 0)
-
-			switch ctxt.BuildMode {
-			case BuildModeCShared, BuildModeCArchive, BuildModePlugin:
-				if s == lookup("main", 0) {
-					continue
-				}
-			}
-
-			// export overrides import, for openbsd/cgo.
-			// see issue 4878.
-			if s.Dynimplib() != "" {
-				s.ResetDyninfo()
-				s.SetExtname("")
-				s.Type = 0
-			}
-
-			if !s.Attr.CgoExport() {
-				s.SetExtname(remote)
-			} else if s.Extname() != remote {
-				fmt.Fprintf(os.Stderr, "%s: conflicting cgo_export directives: %s as %s and %s\n", os.Args[0], s.Name, s.Extname(), remote)
-				nerrors++
-				return
-			}
-
-			if f[0] == "cgo_export_static" {
-				s.Attr |= sym.AttrCgoExportStatic
-			} else {
-				s.Attr |= sym.AttrCgoExportDynamic
-			}
-			continue
-
-		case "cgo_dynamic_linker":
-			if len(f) != 2 {
-				break
-			}
-
-			if *flagInterpreter == "" {
-				if interpreter != "" && interpreter != f[1] {
-					fmt.Fprintf(os.Stderr, "%s: conflict dynlinker: %s and %s\n", os.Args[0], interpreter, f[1])
-					nerrors++
-					return
-				}
-
-				interpreter = f[1]
-			}
-			continue
-
-		case "cgo_ldflag":
-			if len(f) != 2 {
-				break
-			}
-			ldflag = append(ldflag, f[1])
-			continue
-		}
-
-		fmt.Fprintf(os.Stderr, "%s: %s: invalid cgo directive: %q\n", os.Args[0], file, f)
-		nerrors++
-	}
-}
-
-var seenlib = make(map[string]bool)
-
-func adddynlib(ctxt *Link, lib string) {
-	if seenlib[lib] || ctxt.LinkMode == LinkExternal {
-		return
-	}
-	seenlib[lib] = true
-
-	if ctxt.IsELF {
-		s := ctxt.Syms.Lookup(".dynstr", 0)
-		if s.Size == 0 {
-			Addstring(s, "")
-		}
-		Elfwritedynent(ctxt, ctxt.Syms.Lookup(".dynamic", 0), DT_NEEDED, uint64(Addstring(s, lib)))
-	} else {
-		Errorf(nil, "adddynlib: unsupported binary format")
-	}
-}
-
-func Adddynsym(ctxt *Link, s *sym.Symbol) {
-	if s.Dynid >= 0 || ctxt.LinkMode == LinkExternal {
-		return
-	}
-
-	if ctxt.IsELF {
-		elfadddynsym(ctxt, s)
-	} else if ctxt.HeadType == objabi.Hdarwin {
-		Errorf(s, "adddynsym: missed symbol (Extname=%s)", s.Extname())
-	} else if ctxt.HeadType == objabi.Hwindows {
-		// already taken care of
-	} else {
-		Errorf(s, "adddynsym: unsupported binary format")
-	}
-}
-
-func fieldtrack(ctxt *Link) {
-	// record field tracking references
-	var buf bytes.Buffer
-	for _, s := range ctxt.Syms.Allsym {
-		if strings.HasPrefix(s.Name, "go.track.") {
-			s.Attr |= sym.AttrSpecial // do not lay out in data segment
-			s.Attr |= sym.AttrNotInSymbolTable
-			if s.Attr.Reachable() {
-				buf.WriteString(s.Name[9:])
-				for p := ctxt.Reachparent[s]; p != nil; p = ctxt.Reachparent[p] {
-					buf.WriteString("\t")
-					buf.WriteString(p.Name)
-				}
-				buf.WriteString("\n")
-			}
-
-			s.Type = sym.SCONST
-			s.Value = 0
-		}
-	}
-
-	if *flagFieldTrack == "" {
-		return
-	}
-	s := ctxt.Syms.ROLookup(*flagFieldTrack, 0)
-	if s == nil || !s.Attr.Reachable() {
-		return
-	}
-	s.Type = sym.SDATA
-	addstrdata(ctxt, *flagFieldTrack, buf.String())
-}
-
-func (ctxt *Link) addexport() {
-	// Track undefined external symbols during external link.
-	if ctxt.LinkMode == LinkExternal {
-		for _, s := range ctxt.Syms.Allsym {
-			if !s.Attr.Reachable() || s.Attr.Special() || s.Attr.SubSymbol() {
-				continue
-			}
-			if s.Type != sym.STEXT {
-				continue
-			}
-			for i := range s.R {
-				r := &s.R[i]
-				if r.Sym != nil && r.Sym.Type == sym.Sxxx {
-					r.Sym.Type = sym.SUNDEFEXT
-				}
-			}
-		}
-	}
-
-	// TODO(aix)
-	if ctxt.HeadType == objabi.Hdarwin || ctxt.HeadType == objabi.Haix {
-		return
-	}
-
-	for _, exp := range dynexp {
-		Adddynsym(ctxt, exp)
-	}
-	for _, lib := range dynlib {
-		adddynlib(ctxt, lib)
-	}
-}
-
-type Pkg struct {
-	mark    bool
-	checked bool
-	path    string
-	impby   []*Pkg
-}
-
-var pkgall []*Pkg
-
-func (p *Pkg) cycle() *Pkg {
-	if p.checked {
-		return nil
-	}
-
-	if p.mark {
-		nerrors++
-		fmt.Printf("import cycle:\n")
-		fmt.Printf("\t%s\n", p.path)
-		return p
-	}
-
-	p.mark = true
-	for _, q := range p.impby {
-		if bad := q.cycle(); bad != nil {
-			p.mark = false
-			p.checked = true
-			fmt.Printf("\timports %s\n", p.path)
-			if bad == p {
-				return nil
-			}
-			return bad
-		}
-	}
-
-	p.checked = true
-	p.mark = false
-	return nil
-}
-
-func importcycles() {
-	for _, p := range pkgall {
-		p.cycle()
-	}
-}
diff --git a/src/cmd/oldlink/internal/ld/ld.go b/src/cmd/oldlink/internal/ld/ld.go
deleted file mode 100644
index 844580b..0000000
--- a/src/cmd/oldlink/internal/ld/ld.go
+++ /dev/null
@@ -1,217 +0,0 @@
-// Derived from Inferno utils/6l/obj.c and utils/6l/span.c
-// https://bitbucket.org/inferno-os/inferno-os/src/master/utils/6l/obj.c
-// https://bitbucket.org/inferno-os/inferno-os/src/master/utils/6l/span.c
-//
-//	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
-
-import (
-	"cmd/oldlink/internal/sym"
-	"io/ioutil"
-	"log"
-	"os"
-	"path"
-	"path/filepath"
-	"strconv"
-	"strings"
-)
-
-func (ctxt *Link) readImportCfg(file string) {
-	ctxt.PackageFile = make(map[string]string)
-	ctxt.PackageShlib = make(map[string]string)
-	data, err := ioutil.ReadFile(file)
-	if err != nil {
-		log.Fatalf("-importcfg: %v", err)
-	}
-
-	for lineNum, line := range strings.Split(string(data), "\n") {
-		lineNum++ // 1-based
-		line = strings.TrimSpace(line)
-		if line == "" {
-			continue
-		}
-		if line == "" || strings.HasPrefix(line, "#") {
-			continue
-		}
-
-		var verb, args string
-		if i := strings.Index(line, " "); i < 0 {
-			verb = line
-		} else {
-			verb, args = line[:i], strings.TrimSpace(line[i+1:])
-		}
-		var before, after string
-		if i := strings.Index(args, "="); i >= 0 {
-			before, after = args[:i], args[i+1:]
-		}
-		switch verb {
-		default:
-			log.Fatalf("%s:%d: unknown directive %q", file, lineNum, verb)
-		case "packagefile":
-			if before == "" || after == "" {
-				log.Fatalf(`%s:%d: invalid packagefile: syntax is "packagefile path=filename"`, file, lineNum)
-			}
-			ctxt.PackageFile[before] = after
-		case "packageshlib":
-			if before == "" || after == "" {
-				log.Fatalf(`%s:%d: invalid packageshlib: syntax is "packageshlib path=filename"`, file, lineNum)
-			}
-			ctxt.PackageShlib[before] = after
-		}
-	}
-}
-
-func pkgname(ctxt *Link, lib string) string {
-	name := path.Clean(lib)
-
-	// When using importcfg, we have the final package name.
-	if ctxt.PackageFile != nil {
-		return name
-	}
-
-	// runtime.a -> runtime, runtime.6 -> runtime
-	pkg := name
-	if len(pkg) >= 2 && pkg[len(pkg)-2] == '.' {
-		pkg = pkg[:len(pkg)-2]
-	}
-	return pkg
-}
-
-func findlib(ctxt *Link, lib string) (string, bool) {
-	name := path.Clean(lib)
-
-	var pname string
-	isshlib := false
-
-	if ctxt.linkShared && ctxt.PackageShlib[name] != "" {
-		pname = ctxt.PackageShlib[name]
-		isshlib = true
-	} else if ctxt.PackageFile != nil {
-		pname = ctxt.PackageFile[name]
-		if pname == "" {
-			ctxt.Logf("cannot find package %s (using -importcfg)\n", name)
-			return "", false
-		}
-	} else {
-		if filepath.IsAbs(name) {
-			pname = name
-		} else {
-			pkg := pkgname(ctxt, lib)
-			// Add .a if needed; the new -importcfg modes
-			// do not put .a into the package name anymore.
-			// This only matters when people try to mix
-			// compiles using -importcfg with links not using -importcfg,
-			// such as when running quick things like
-			// 'go tool compile x.go && go tool link x.o'
-			// by hand against a standard library built using -importcfg.
-			if !strings.HasSuffix(name, ".a") && !strings.HasSuffix(name, ".o") {
-				name += ".a"
-			}
-			// try dot, -L "libdir", and then goroot.
-			for _, dir := range ctxt.Libdir {
-				if ctxt.linkShared {
-					pname = filepath.Join(dir, pkg+".shlibname")
-					if _, err := os.Stat(pname); err == nil {
-						isshlib = true
-						break
-					}
-				}
-				pname = filepath.Join(dir, name)
-				if _, err := os.Stat(pname); err == nil {
-					break
-				}
-			}
-		}
-		pname = filepath.Clean(pname)
-	}
-
-	return pname, isshlib
-}
-
-func addlib(ctxt *Link, src string, obj string, lib string) *sym.Library {
-	pkg := pkgname(ctxt, lib)
-
-	// already loaded?
-	if l := ctxt.LibraryByPkg[pkg]; l != nil {
-		return l
-	}
-
-	pname, isshlib := findlib(ctxt, lib)
-
-	if ctxt.Debugvlog > 1 {
-		ctxt.Logf("addlib: %s %s pulls in %s isshlib %v\n", obj, src, pname, isshlib)
-	}
-
-	if isshlib {
-		return addlibpath(ctxt, src, obj, "", pkg, pname)
-	}
-	return addlibpath(ctxt, src, obj, pname, pkg, "")
-}
-
-/*
- * add library to library list, return added library.
- *	srcref: src file referring to package
- *	objref: object file referring to package
- *	file: object file, e.g., /home/rsc/go/pkg/container/vector.a
- *	pkg: package import path, e.g. container/vector
- *	shlib: path to shared library, or .shlibname file holding path
- */
-func addlibpath(ctxt *Link, srcref string, objref string, file string, pkg string, shlib string) *sym.Library {
-	if l := ctxt.LibraryByPkg[pkg]; l != nil {
-		return l
-	}
-
-	if ctxt.Debugvlog > 1 {
-		ctxt.Logf("addlibpath: srcref: %s objref: %s file: %s pkg: %s shlib: %s\n", srcref, objref, file, pkg, shlib)
-	}
-
-	l := &sym.Library{}
-	ctxt.LibraryByPkg[pkg] = l
-	ctxt.Library = append(ctxt.Library, l)
-	l.Objref = objref
-	l.Srcref = srcref
-	l.File = file
-	l.Pkg = pkg
-	if shlib != "" {
-		if strings.HasSuffix(shlib, ".shlibname") {
-			data, err := ioutil.ReadFile(shlib)
-			if err != nil {
-				Errorf(nil, "cannot read %s: %v", shlib, err)
-			}
-			shlib = strings.TrimSpace(string(data))
-		}
-		l.Shlib = shlib
-	}
-	return l
-}
-
-func atolwhex(s string) int64 {
-	n, _ := strconv.ParseInt(s, 0, 64)
-	return n
-}
diff --git a/src/cmd/oldlink/internal/ld/lib.go b/src/cmd/oldlink/internal/ld/lib.go
deleted file mode 100644
index cc42901..0000000
--- a/src/cmd/oldlink/internal/ld/lib.go
+++ /dev/null
@@ -1,2749 +0,0 @@
-// Inferno utils/8l/asm.c
-// https://bitbucket.org/inferno-os/inferno-os/src/master/utils/8l/asm.c
-//
-//	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
-
-import (
-	"bufio"
-	"bytes"
-	"cmd/internal/bio"
-	"cmd/internal/obj"
-	"cmd/internal/objabi"
-	"cmd/internal/sys"
-	"cmd/oldlink/internal/loadelf"
-	"cmd/oldlink/internal/loader"
-	"cmd/oldlink/internal/loadmacho"
-	"cmd/oldlink/internal/loadpe"
-	"cmd/oldlink/internal/loadxcoff"
-	"cmd/oldlink/internal/objfile"
-	"cmd/oldlink/internal/sym"
-	"crypto/sha1"
-	"debug/elf"
-	"debug/macho"
-	"encoding/base64"
-	"encoding/binary"
-	"encoding/hex"
-	"fmt"
-	"io"
-	"io/ioutil"
-	"log"
-	"os"
-	"os/exec"
-	"path/filepath"
-	"runtime"
-	"sort"
-	"strings"
-	"sync"
-)
-
-// Data layout and relocation.
-
-// Derived from Inferno utils/6l/l.h
-// https://bitbucket.org/inferno-os/inferno-os/src/master/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.
-
-type Arch struct {
-	Funcalign      int
-	Maxalign       int
-	Minalign       int
-	Dwarfregsp     int
-	Dwarfreglr     int
-	Androiddynld   string
-	Linuxdynld     string
-	Freebsddynld   string
-	Netbsddynld    string
-	Openbsddynld   string
-	Dragonflydynld string
-	Solarisdynld   string
-	Adddynrel      func(*Link, *sym.Symbol, *sym.Reloc) bool
-	Archinit       func(*Link)
-	// Archreloc is an arch-specific hook that assists in
-	// relocation processing (invoked by 'relocsym'); it handles
-	// target-specific relocation tasks. Here "rel" is the current
-	// relocation being examined, "sym" is the symbol containing the
-	// chunk of data to which the relocation applies, and "off" is the
-	// contents of the to-be-relocated data item (from sym.P). Return
-	// value is the appropriately relocated value (to be written back
-	// to the same spot in sym.P) and a boolean indicating
-	// success/failure (a failing value indicates a fatal error).
-	Archreloc func(link *Link, rel *sym.Reloc, sym *sym.Symbol,
-		offset int64) (relocatedOffset int64, success bool)
-	// Archrelocvariant is a second arch-specific hook used for
-	// relocation processing; it handles relocations where r.Type is
-	// insufficient to describe the relocation (r.Variant !=
-	// sym.RV_NONE). Here "rel" is the relocation being applied, "sym"
-	// is the symbol containing the chunk of data to which the
-	// relocation applies, and "off" is the contents of the
-	// to-be-relocated data item (from sym.P). Return is an updated
-	// offset value.
-	Archrelocvariant func(link *Link, rel *sym.Reloc, sym *sym.Symbol,
-		offset int64) (relocatedOffset int64)
-	Trampoline func(*Link, *sym.Reloc, *sym.Symbol)
-
-	// Asmb and Asmb2 are arch-specific routines that write the output
-	// file. Typically, Asmb writes most of the content (sections and
-	// segments), for which we have computed the size and offset. Asmb2
-	// writes the rest.
-	Asmb  func(*Link)
-	Asmb2 func(*Link)
-
-	Elfreloc1   func(*Link, *sym.Reloc, int64) bool
-	Elfsetupplt func(*Link)
-	Gentext     func(*Link)
-	Machoreloc1 func(*sys.Arch, *OutBuf, *sym.Symbol, *sym.Reloc, int64) bool
-	PEreloc1    func(*sys.Arch, *OutBuf, *sym.Symbol, *sym.Reloc, int64) bool
-	Xcoffreloc1 func(*sys.Arch, *OutBuf, *sym.Symbol, *sym.Reloc, int64) bool
-
-	// TLSIEtoLE converts a TLS Initial Executable relocation to
-	// a TLS Local Executable relocation.
-	//
-	// This is possible when a TLS IE relocation refers to a local
-	// symbol in an executable, which is typical when internally
-	// linking PIE binaries.
-	TLSIEtoLE func(s *sym.Symbol, off, size int)
-
-	// optional override for assignAddress
-	AssignAddress func(ctxt *Link, sect *sym.Section, n int, s *sym.Symbol, va uint64, isTramp bool) (*sym.Section, int, uint64)
-}
-
-var (
-	thearch Arch
-	Lcsize  int32
-	rpath   Rpath
-	Spsize  int32
-	Symsize int32
-)
-
-const (
-	MINFUNC = 16 // minimum size for a function
-)
-
-// DynlinkingGo reports whether we are producing Go code that can live
-// in separate shared libraries linked together at runtime.
-func (ctxt *Link) DynlinkingGo() bool {
-	if !ctxt.Loaded {
-		panic("DynlinkingGo called before all symbols loaded")
-	}
-	return ctxt.BuildMode == BuildModeShared || ctxt.linkShared || ctxt.BuildMode == BuildModePlugin || ctxt.canUsePlugins
-}
-
-// CanUsePlugins reports whether a plugins can be used
-func (ctxt *Link) CanUsePlugins() bool {
-	if !ctxt.Loaded {
-		panic("CanUsePlugins called before all symbols loaded")
-	}
-	return ctxt.canUsePlugins
-}
-
-// UseRelro reports whether to make use of "read only relocations" aka
-// relro.
-func (ctxt *Link) UseRelro() bool {
-	switch ctxt.BuildMode {
-	case BuildModeCArchive, BuildModeCShared, BuildModeShared, BuildModePIE, BuildModePlugin:
-		return ctxt.IsELF || ctxt.HeadType == objabi.Haix
-	default:
-		return ctxt.linkShared || (ctxt.HeadType == objabi.Haix && ctxt.LinkMode == LinkExternal)
-	}
-}
-
-var (
-	dynexp          []*sym.Symbol
-	dynlib          []string
-	ldflag          []string
-	havedynamic     int
-	Funcalign       int
-	iscgo           bool
-	elfglobalsymndx int
-	interpreter     string
-
-	debug_s bool // backup old value of debug['s']
-	HEADR   int32
-
-	nerrors  int
-	liveness int64
-
-	// See -strictdups command line flag.
-	checkStrictDups   int // 0=off 1=warning 2=error
-	strictDupMsgCount int
-)
-
-var (
-	Segtext      sym.Segment
-	Segrodata    sym.Segment
-	Segrelrodata sym.Segment
-	Segdata      sym.Segment
-	Segdwarf     sym.Segment
-)
-
-const pkgdef = "__.PKGDEF"
-
-var (
-	// Set if we see an object compiled by the host compiler that is not
-	// from a package that is known to support internal linking mode.
-	externalobj = false
-	theline     string
-)
-
-func Lflag(ctxt *Link, arg string) {
-	ctxt.Libdir = append(ctxt.Libdir, arg)
-}
-
-/*
- * Unix doesn't like it when we write to a running (or, sometimes,
- * recently run) binary, so remove the output file before writing it.
- * On Windows 7, remove() can force a subsequent create() to fail.
- * S_ISREG() does not exist on Plan 9.
- */
-func mayberemoveoutfile() {
-	if fi, err := os.Lstat(*flagOutfile); err == nil && !fi.Mode().IsRegular() {
-		return
-	}
-	os.Remove(*flagOutfile)
-}
-
-func libinit(ctxt *Link) {
-	Funcalign = thearch.Funcalign
-
-	// add goroot to the end of the libdir list.
-	suffix := ""
-
-	suffixsep := ""
-	if *flagInstallSuffix != "" {
-		suffixsep = "_"
-		suffix = *flagInstallSuffix
-	} else if *flagRace {
-		suffixsep = "_"
-		suffix = "race"
-	} else if *flagMsan {
-		suffixsep = "_"
-		suffix = "msan"
-	}
-
-	Lflag(ctxt, filepath.Join(objabi.GOROOT, "pkg", fmt.Sprintf("%s_%s%s%s", objabi.GOOS, objabi.GOARCH, suffixsep, suffix)))
-
-	mayberemoveoutfile()
-	f, err := os.OpenFile(*flagOutfile, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0775)
-	if err != nil {
-		Exitf("cannot create %s: %v", *flagOutfile, err)
-	}
-
-	ctxt.Out.w = bufio.NewWriter(f)
-	ctxt.Out.f = f
-
-	if *flagEntrySymbol == "" {
-		switch ctxt.BuildMode {
-		case BuildModeCShared, BuildModeCArchive:
-			*flagEntrySymbol = fmt.Sprintf("_rt0_%s_%s_lib", objabi.GOARCH, objabi.GOOS)
-		case BuildModeExe, BuildModePIE:
-			*flagEntrySymbol = fmt.Sprintf("_rt0_%s_%s", objabi.GOARCH, objabi.GOOS)
-		case BuildModeShared, BuildModePlugin:
-			// No *flagEntrySymbol for -buildmode=shared and plugin
-		default:
-			Errorf(nil, "unknown *flagEntrySymbol for buildmode %v", ctxt.BuildMode)
-		}
-	}
-}
-
-func exitIfErrors() {
-	if nerrors != 0 || checkStrictDups > 1 && strictDupMsgCount > 0 {
-		mayberemoveoutfile()
-		Exit(2)
-	}
-
-}
-
-func errorexit() {
-	exitIfErrors()
-	Exit(0)
-}
-
-func loadinternal(ctxt *Link, name string) *sym.Library {
-	if ctxt.linkShared && ctxt.PackageShlib != nil {
-		if shlib := ctxt.PackageShlib[name]; shlib != "" {
-			return addlibpath(ctxt, "internal", "internal", "", name, shlib)
-		}
-	}
-	if ctxt.PackageFile != nil {
-		if pname := ctxt.PackageFile[name]; pname != "" {
-			return addlibpath(ctxt, "internal", "internal", pname, name, "")
-		}
-		ctxt.Logf("loadinternal: cannot find %s\n", name)
-		return nil
-	}
-
-	for _, libdir := range ctxt.Libdir {
-		if ctxt.linkShared {
-			shlibname := filepath.Join(libdir, name+".shlibname")
-			if ctxt.Debugvlog != 0 {
-				ctxt.Logf("searching for %s.a in %s\n", name, shlibname)
-			}
-			if _, err := os.Stat(shlibname); err == nil {
-				return addlibpath(ctxt, "internal", "internal", "", name, shlibname)
-			}
-		}
-		pname := filepath.Join(libdir, name+".a")
-		if ctxt.Debugvlog != 0 {
-			ctxt.Logf("searching for %s.a in %s\n", name, pname)
-		}
-		if _, err := os.Stat(pname); err == nil {
-			return addlibpath(ctxt, "internal", "internal", pname, name, "")
-		}
-	}
-
-	ctxt.Logf("warning: unable to find %s.a\n", name)
-	return nil
-}
-
-// extld returns the current external linker.
-func (ctxt *Link) extld() string {
-	if *flagExtld == "" {
-		*flagExtld = "gcc"
-	}
-	return *flagExtld
-}
-
-// findLibPathCmd uses cmd command to find gcc library libname.
-// It returns library full path if found, or "none" if not found.
-func (ctxt *Link) findLibPathCmd(cmd, libname string) string {
-	extld := ctxt.extld()
-	args := hostlinkArchArgs(ctxt.Arch)
-	args = append(args, cmd)
-	if ctxt.Debugvlog != 0 {
-		ctxt.Logf("%s %v\n", extld, args)
-	}
-	out, err := exec.Command(extld, args...).Output()
-	if err != nil {
-		if ctxt.Debugvlog != 0 {
-			ctxt.Logf("not using a %s file because compiler failed\n%v\n%s\n", libname, err, out)
-		}
-		return "none"
-	}
-	return strings.TrimSpace(string(out))
-}
-
-// findLibPath searches for library libname.
-// It returns library full path if found, or "none" if not found.
-func (ctxt *Link) findLibPath(libname string) string {
-	return ctxt.findLibPathCmd("--print-file-name="+libname, libname)
-}
-
-func (ctxt *Link) loadlib() {
-	if *flagNewobj {
-		var flags uint32
-		switch *FlagStrictDups {
-		case 0:
-			// nothing to do
-		case 1, 2:
-			flags = loader.FlagStrictDups
-		default:
-			log.Fatalf("invalid -strictdups flag value %d", *FlagStrictDups)
-		}
-		ctxt.loader = loader.NewLoader(flags)
-	}
-
-	ctxt.cgo_export_static = make(map[string]bool)
-	ctxt.cgo_export_dynamic = make(map[string]bool)
-
-	// ctxt.Library grows during the loop, so not a range loop.
-	i := 0
-	for ; i < len(ctxt.Library); i++ {
-		lib := ctxt.Library[i]
-		if lib.Shlib == "" {
-			if ctxt.Debugvlog > 1 {
-				ctxt.Logf("autolib: %s (from %s)\n", lib.File, lib.Objref)
-			}
-			loadobjfile(ctxt, lib)
-		}
-	}
-
-	// load internal packages, if not already
-	if *flagRace {
-		loadinternal(ctxt, "runtime/race")
-	}
-	if *flagMsan {
-		loadinternal(ctxt, "runtime/msan")
-	}
-	loadinternal(ctxt, "runtime")
-	for ; i < len(ctxt.Library); i++ {
-		lib := ctxt.Library[i]
-		if lib.Shlib == "" {
-			loadobjfile(ctxt, lib)
-		}
-	}
-
-	if *flagNewobj {
-		iscgo = ctxt.loader.Lookup("x_cgo_init", 0) != 0
-		ctxt.canUsePlugins = ctxt.loader.Lookup("plugin.Open", sym.SymVerABIInternal) != 0
-	} else {
-		iscgo = ctxt.Syms.ROLookup("x_cgo_init", 0) != nil
-		ctxt.canUsePlugins = ctxt.Syms.ROLookup("plugin.Open", sym.SymVerABIInternal) != nil
-	}
-
-	// We now have enough information to determine the link mode.
-	determineLinkMode(ctxt)
-
-	if ctxt.LinkMode == LinkExternal && !iscgo && ctxt.LibraryByPkg["runtime/cgo"] == nil && !(objabi.GOOS == "darwin" && ctxt.BuildMode != BuildModePlugin && ctxt.Arch.Family == sys.AMD64) {
-		// This indicates a user requested -linkmode=external.
-		// The startup code uses an import of runtime/cgo to decide
-		// whether to initialize the TLS.  So give it one. This could
-		// be handled differently but it's an unusual case.
-		if lib := loadinternal(ctxt, "runtime/cgo"); lib != nil {
-			if lib.Shlib != "" {
-				ldshlibsyms(ctxt, lib.Shlib)
-			} else {
-				if ctxt.BuildMode == BuildModeShared || ctxt.linkShared {
-					Exitf("cannot implicitly include runtime/cgo in a shared library")
-				}
-				loadobjfile(ctxt, lib)
-			}
-		}
-	}
-
-	for _, lib := range ctxt.Library {
-		if lib.Shlib != "" {
-			if ctxt.Debugvlog > 1 {
-				ctxt.Logf("autolib: %s (from %s)\n", lib.Shlib, lib.Objref)
-			}
-			ldshlibsyms(ctxt, lib.Shlib)
-		}
-	}
-
-	if ctxt.LinkMode == LinkInternal && len(hostobj) != 0 {
-		if *flagNewobj {
-			// In newobj mode, we typically create sym.Symbols later therefore
-			// also set cgo attributes later. However, for internal cgo linking,
-			// the host object loaders still work with sym.Symbols (for now),
-			// and they need cgo attributes set to work properly. So process
-			// them now.
-			lookup := func(name string, ver int) *sym.Symbol { return ctxt.loader.LookupOrCreate(name, ver, ctxt.Syms) }
-			for _, d := range ctxt.cgodata {
-				setCgoAttr(ctxt, lookup, d.file, d.pkg, d.directives)
-			}
-			ctxt.cgodata = nil
-		}
-
-		// Drop all the cgo_import_static declarations.
-		// Turns out we won't be needing them.
-		for _, s := range ctxt.Syms.Allsym {
-			if s.Type == sym.SHOSTOBJ {
-				// If a symbol was marked both
-				// cgo_import_static and cgo_import_dynamic,
-				// then we want to make it cgo_import_dynamic
-				// now.
-				if s.Extname() != "" && s.Dynimplib() != "" && !s.Attr.CgoExport() {
-					s.Type = sym.SDYNIMPORT
-				} else {
-					s.Type = 0
-				}
-			}
-		}
-	}
-
-	// Conditionally load host objects, or setup for external linking.
-	hostobjs(ctxt)
-	hostlinksetup(ctxt)
-
-	if *flagNewobj {
-		// Add references of externally defined symbols.
-		ctxt.loader.LoadRefs(ctxt.Arch, ctxt.Syms)
-	}
-
-	// Now that we know the link mode, set the dynexp list.
-	if !*flagNewobj { // set this later in newobj mode
-		setupdynexp(ctxt)
-	}
-
-	if ctxt.LinkMode == LinkInternal && len(hostobj) != 0 {
-		// If we have any undefined symbols in external
-		// objects, try to read them from the libgcc file.
-		any := false
-		for _, s := range ctxt.Syms.Allsym {
-			for i := range s.R {
-				r := &s.R[i] // Copying sym.Reloc has measurable impact on performance
-				if r.Sym != nil && r.Sym.Type == sym.SXREF && r.Sym.Name != ".got" {
-					any = true
-					break
-				}
-			}
-		}
-		if any {
-			if *flagLibGCC == "" {
-				*flagLibGCC = ctxt.findLibPathCmd("--print-libgcc-file-name", "libgcc")
-			}
-			if runtime.GOOS == "openbsd" && *flagLibGCC == "libgcc.a" {
-				// On OpenBSD `clang --print-libgcc-file-name` returns "libgcc.a".
-				// In this case we fail to load libgcc.a and can encounter link
-				// errors - see if we can find libcompiler_rt.a instead.
-				*flagLibGCC = ctxt.findLibPathCmd("--print-file-name=libcompiler_rt.a", "libcompiler_rt")
-			}
-			if *flagLibGCC != "none" {
-				hostArchive(ctxt, *flagLibGCC)
-			}
-			if ctxt.HeadType == objabi.Hwindows {
-				if p := ctxt.findLibPath("libmingwex.a"); p != "none" {
-					hostArchive(ctxt, p)
-				}
-				if p := ctxt.findLibPath("libmingw32.a"); p != "none" {
-					hostArchive(ctxt, p)
-				}
-				// Link libmsvcrt.a to resolve '__acrt_iob_func' symbol
-				// (see https://golang.org/issue/23649 for details).
-				if p := ctxt.findLibPath("libmsvcrt.a"); p != "none" {
-					hostArchive(ctxt, p)
-				}
-				// TODO: maybe do something similar to peimporteddlls to collect all lib names
-				// and try link them all to final exe just like libmingwex.a and libmingw32.a:
-				/*
-					for:
-					#cgo windows LDFLAGS: -lmsvcrt -lm
-					import:
-					libmsvcrt.a libm.a
-				*/
-			}
-		}
-	}
-
-	// We've loaded all the code now.
-	ctxt.Loaded = true
-
-	importcycles()
-
-	if *flagNewobj {
-		strictDupMsgCount = ctxt.loader.NStrictDupMsgs()
-	}
-}
-
-// Set up dynexp list.
-func setupdynexp(ctxt *Link) {
-	dynexpMap := ctxt.cgo_export_dynamic
-	if ctxt.LinkMode == LinkExternal {
-		dynexpMap = ctxt.cgo_export_static
-	}
-	dynexp = make([]*sym.Symbol, 0, len(dynexpMap))
-	for exp := range dynexpMap {
-		s := ctxt.Syms.Lookup(exp, 0)
-		dynexp = append(dynexp, s)
-	}
-	sort.Sort(byName(dynexp))
-
-	// Resolve ABI aliases in the list of cgo-exported functions.
-	// This is necessary because we load the ABI0 symbol for all
-	// cgo exports.
-	for i, s := range dynexp {
-		if s.Type != sym.SABIALIAS {
-			continue
-		}
-		t := resolveABIAlias(s)
-		t.Attr |= s.Attr
-		t.SetExtname(s.Extname())
-		dynexp[i] = t
-	}
-
-	ctxt.cgo_export_static = nil
-	ctxt.cgo_export_dynamic = nil
-}
-
-// Set up flags and special symbols depending on the platform build mode.
-func (ctxt *Link) linksetup() {
-	switch ctxt.BuildMode {
-	case BuildModeCShared, BuildModePlugin:
-		s := ctxt.Syms.Lookup("runtime.islibrary", 0)
-		s.Type = sym.SNOPTRDATA
-		s.Attr |= sym.AttrDuplicateOK
-		s.AddUint8(1)
-	case BuildModeCArchive:
-		s := ctxt.Syms.Lookup("runtime.isarchive", 0)
-		s.Type = sym.SNOPTRDATA
-		s.Attr |= sym.AttrDuplicateOK
-		s.AddUint8(1)
-	}
-
-	// Recalculate pe parameters now that we have ctxt.LinkMode set.
-	if ctxt.HeadType == objabi.Hwindows {
-		Peinit(ctxt)
-	}
-
-	if ctxt.HeadType == objabi.Hdarwin && ctxt.LinkMode == LinkExternal {
-		*FlagTextAddr = 0
-	}
-
-	// If there are no dynamic libraries needed, gcc disables dynamic linking.
-	// Because of this, glibc's dynamic ELF loader occasionally (like in version 2.13)
-	// assumes that a dynamic binary always refers to at least one dynamic library.
-	// Rather than be a source of test cases for glibc, disable dynamic linking
-	// the same way that gcc would.
-	//
-	// Exception: on OS X, programs such as Shark only work with dynamic
-	// binaries, so leave it enabled on OS X (Mach-O) binaries.
-	// Also leave it enabled on Solaris which doesn't support
-	// statically linked binaries.
-	if ctxt.BuildMode == BuildModeExe {
-		if havedynamic == 0 && ctxt.HeadType != objabi.Hdarwin && ctxt.HeadType != objabi.Hsolaris {
-			*FlagD = true
-		}
-	}
-
-	if ctxt.LinkMode == LinkExternal && ctxt.Arch.Family == sys.PPC64 && objabi.GOOS != "aix" {
-		toc := ctxt.Syms.Lookup(".TOC.", 0)
-		toc.Type = sym.SDYNIMPORT
-	}
-
-	// The Android Q linker started to complain about underalignment of the our TLS
-	// section. We don't actually use the section on android, so dont't
-	// generate it.
-	if objabi.GOOS != "android" {
-		tlsg := ctxt.Syms.Lookup("runtime.tlsg", 0)
-
-		// runtime.tlsg is used for external linking on platforms that do not define
-		// a variable to hold g in assembly (currently only intel).
-		if tlsg.Type == 0 {
-			tlsg.Type = sym.STLSBSS
-			tlsg.Size = int64(ctxt.Arch.PtrSize)
-		} else if tlsg.Type != sym.SDYNIMPORT {
-			Errorf(nil, "runtime declared tlsg variable %v", tlsg.Type)
-		}
-		tlsg.Attr |= sym.AttrReachable
-		ctxt.Tlsg = tlsg
-	}
-
-	var moduledata *sym.Symbol
-	if ctxt.BuildMode == BuildModePlugin {
-		moduledata = ctxt.Syms.Lookup("local.pluginmoduledata", 0)
-		moduledata.Attr |= sym.AttrLocal
-	} else {
-		moduledata = ctxt.Syms.Lookup("runtime.firstmoduledata", 0)
-	}
-	if moduledata.Type != 0 && moduledata.Type != sym.SDYNIMPORT {
-		// If the module (toolchain-speak for "executable or shared
-		// library") we are linking contains the runtime package, it
-		// will define the runtime.firstmoduledata symbol and we
-		// truncate it back to 0 bytes so we can define its entire
-		// contents in symtab.go:symtab().
-		moduledata.Size = 0
-
-		// In addition, on ARM, the runtime depends on the linker
-		// recording the value of GOARM.
-		if ctxt.Arch.Family == sys.ARM {
-			s := ctxt.Syms.Lookup("runtime.goarm", 0)
-			s.Type = sym.SDATA
-			s.Size = 0
-			s.AddUint8(uint8(objabi.GOARM))
-		}
-
-		if objabi.Framepointer_enabled(objabi.GOOS, objabi.GOARCH) {
-			s := ctxt.Syms.Lookup("runtime.framepointer_enabled", 0)
-			s.Type = sym.SDATA
-			s.Size = 0
-			s.AddUint8(1)
-		}
-	} else {
-		// If OTOH the module does not contain the runtime package,
-		// create a local symbol for the moduledata.
-		moduledata = ctxt.Syms.Lookup("local.moduledata", 0)
-		moduledata.Attr |= sym.AttrLocal
-	}
-	// In all cases way we mark the moduledata as noptrdata to hide it from
-	// the GC.
-	moduledata.Type = sym.SNOPTRDATA
-	moduledata.Attr |= sym.AttrReachable
-	ctxt.Moduledata = moduledata
-
-	// If package versioning is required, generate a hash of the
-	// packages used in the link.
-	if ctxt.BuildMode == BuildModeShared || ctxt.BuildMode == BuildModePlugin || ctxt.CanUsePlugins() {
-		for _, lib := range ctxt.Library {
-			if lib.Shlib == "" {
-				genhash(ctxt, lib)
-			}
-		}
-	}
-
-	if ctxt.Arch == sys.Arch386 && ctxt.HeadType != objabi.Hwindows {
-		if (ctxt.BuildMode == BuildModeCArchive && ctxt.IsELF) || ctxt.BuildMode == BuildModeCShared || ctxt.BuildMode == BuildModePIE || ctxt.DynlinkingGo() {
-			got := ctxt.Syms.Lookup("_GLOBAL_OFFSET_TABLE_", 0)
-			got.Type = sym.SDYNIMPORT
-			got.Attr |= sym.AttrReachable
-		}
-	}
-}
-
-// mangleTypeSym shortens the names of symbols that represent Go types
-// if they are visible in the symbol table.
-//
-// As the names of these symbols are derived from the string of
-// the type, they can run to many kilobytes long. So we shorten
-// them using a SHA-1 when the name appears in the final binary.
-// This also removes characters that upset external linkers.
-//
-// These are the symbols that begin with the prefix 'type.' and
-// contain run-time type information used by the runtime and reflect
-// packages. All Go binaries contain these symbols, but only
-// those programs loaded dynamically in multiple parts need these
-// symbols to have entries in the symbol table.
-func (ctxt *Link) mangleTypeSym() {
-	if ctxt.BuildMode != BuildModeShared && !ctxt.linkShared && ctxt.BuildMode != BuildModePlugin && !ctxt.CanUsePlugins() {
-		return
-	}
-
-	for _, s := range ctxt.Syms.Allsym {
-		newName := typeSymbolMangle(s.Name)
-		if newName != s.Name {
-			ctxt.Syms.Rename(s.Name, newName, int(s.Version), ctxt.Reachparent)
-		}
-	}
-}
-
-// typeSymbolMangle mangles the given symbol name into something shorter.
-//
-// Keep the type.. prefix, which parts of the linker (like the
-// DWARF generator) know means the symbol is not decodable.
-// Leave type.runtime. symbols alone, because other parts of
-// the linker manipulates them.
-func typeSymbolMangle(name string) string {
-	if !strings.HasPrefix(name, "type.") {
-		return name
-	}
-	if strings.HasPrefix(name, "type.runtime.") {
-		return name
-	}
-	if len(name) <= 14 && !strings.Contains(name, "@") { // Issue 19529
-		return name
-	}
-	hash := sha1.Sum([]byte(name))
-	prefix := "type."
-	if name[5] == '.' {
-		prefix = "type.."
-	}
-	return prefix + base64.StdEncoding.EncodeToString(hash[:6])
-}
-
-/*
- * look for the next file in an archive.
- * adapted from libmach.
- */
-func nextar(bp *bio.Reader, off int64, a *ArHdr) int64 {
-	if off&1 != 0 {
-		off++
-	}
-	bp.MustSeek(off, 0)
-	var buf [SAR_HDR]byte
-	if n, err := io.ReadFull(bp, buf[:]); err != nil {
-		if n == 0 && err != io.EOF {
-			return -1
-		}
-		return 0
-	}
-
-	a.name = artrim(buf[0:16])
-	a.date = artrim(buf[16:28])
-	a.uid = artrim(buf[28:34])
-	a.gid = artrim(buf[34:40])
-	a.mode = artrim(buf[40:48])
-	a.size = artrim(buf[48:58])
-	a.fmag = artrim(buf[58:60])
-
-	arsize := atolwhex(a.size)
-	if arsize&1 != 0 {
-		arsize++
-	}
-	return arsize + SAR_HDR
-}
-
-func genhash(ctxt *Link, lib *sym.Library) {
-	f, err := bio.Open(lib.File)
-	if err != nil {
-		Errorf(nil, "cannot open file %s for hash generation: %v", lib.File, err)
-		return
-	}
-	defer f.Close()
-
-	var magbuf [len(ARMAG)]byte
-	if _, err := io.ReadFull(f, magbuf[:]); err != nil {
-		Exitf("file %s too short", lib.File)
-	}
-
-	if string(magbuf[:]) != ARMAG {
-		Exitf("%s is not an archive file", lib.File)
-	}
-
-	var arhdr ArHdr
-	l := nextar(f, f.Offset(), &arhdr)
-	if l <= 0 {
-		Errorf(nil, "%s: short read on archive file symbol header", lib.File)
-		return
-	}
-	if arhdr.name != pkgdef {
-		Errorf(nil, "%s: missing package data entry", lib.File)
-		return
-	}
-
-	h := sha1.New()
-
-	// To compute the hash of a package, we hash the first line of
-	// __.PKGDEF (which contains the toolchain version and any
-	// GOEXPERIMENT flags) and the export data (which is between
-	// the first two occurrences of "\n$$").
-
-	pkgDefBytes := make([]byte, atolwhex(arhdr.size))
-	_, err = io.ReadFull(f, pkgDefBytes)
-	if err != nil {
-		Errorf(nil, "%s: error reading package data: %v", lib.File, err)
-		return
-	}
-	firstEOL := bytes.IndexByte(pkgDefBytes, '\n')
-	if firstEOL < 0 {
-		Errorf(nil, "cannot parse package data of %s for hash generation, no newline found", lib.File)
-		return
-	}
-	firstDoubleDollar := bytes.Index(pkgDefBytes, []byte("\n$$"))
-	if firstDoubleDollar < 0 {
-		Errorf(nil, "cannot parse package data of %s for hash generation, no \\n$$ found", lib.File)
-		return
-	}
-	secondDoubleDollar := bytes.Index(pkgDefBytes[firstDoubleDollar+1:], []byte("\n$$"))
-	if secondDoubleDollar < 0 {
-		Errorf(nil, "cannot parse package data of %s for hash generation, only one \\n$$ found", lib.File)
-		return
-	}
-	h.Write(pkgDefBytes[0:firstEOL])
-	h.Write(pkgDefBytes[firstDoubleDollar : firstDoubleDollar+secondDoubleDollar])
-	lib.Hash = hex.EncodeToString(h.Sum(nil))
-}
-
-func loadobjfile(ctxt *Link, lib *sym.Library) {
-	pkg := objabi.PathToPrefix(lib.Pkg)
-
-	if ctxt.Debugvlog > 1 {
-		ctxt.Logf("ldobj: %s (%s)\n", lib.File, pkg)
-	}
-	f, err := bio.Open(lib.File)
-	if err != nil {
-		Exitf("cannot open file %s: %v", lib.File, err)
-	}
-	defer f.Close()
-	defer func() {
-		if pkg == "main" && !lib.Main {
-			Exitf("%s: not package main", lib.File)
-		}
-
-		// Ideally, we'd check that *all* object files within
-		// the archive were marked safe, but here we settle
-		// for *any*.
-		//
-		// Historically, cmd/link only checked the __.PKGDEF
-		// file, which in turn came from the first object
-		// file, typically produced by cmd/compile. The
-		// remaining object files are normally produced by
-		// cmd/asm, which doesn't support marking files as
-		// safe anyway. So at least in practice, this matches
-		// how safe mode has always worked.
-		if *flagU && !lib.Safe {
-			Exitf("%s: load of unsafe package %s", lib.File, pkg)
-		}
-	}()
-
-	for i := 0; i < len(ARMAG); i++ {
-		if c, err := f.ReadByte(); err == nil && c == ARMAG[i] {
-			continue
-		}
-
-		/* load it as a regular file */
-		l := f.MustSeek(0, 2)
-		f.MustSeek(0, 0)
-		ldobj(ctxt, f, lib, l, lib.File, lib.File)
-		return
-	}
-
-	/*
-	 * load all the object files from the archive now.
-	 * this gives us sequential file access and keeps us
-	 * from needing to come back later to pick up more
-	 * objects.  it breaks the usual C archive model, but
-	 * this is Go, not C.  the common case in Go is that
-	 * we need to load all the objects, and then we throw away
-	 * the individual symbols that are unused.
-	 *
-	 * loading every object will also make it possible to
-	 * load foreign objects not referenced by __.PKGDEF.
-	 */
-	var arhdr ArHdr
-	off := f.Offset()
-	for {
-		l := nextar(f, off, &arhdr)
-		if l == 0 {
-			break
-		}
-		if l < 0 {
-			Exitf("%s: malformed archive", lib.File)
-		}
-		off += l
-
-		// __.PKGDEF isn't a real Go object file, and it's
-		// absent in -linkobj builds anyway. Skipping it
-		// ensures consistency between -linkobj and normal
-		// build modes.
-		if arhdr.name == pkgdef {
-			continue
-		}
-
-		// Skip other special (non-object-file) sections that
-		// build tools may have added. Such sections must have
-		// short names so that the suffix is not truncated.
-		if len(arhdr.name) < 16 {
-			if ext := filepath.Ext(arhdr.name); ext != ".o" && ext != ".syso" {
-				continue
-			}
-		}
-
-		pname := fmt.Sprintf("%s(%s)", lib.File, arhdr.name)
-		l = atolwhex(arhdr.size)
-		ldobj(ctxt, f, lib, l, pname, lib.File)
-	}
-}
-
-type Hostobj struct {
-	ld     func(*Link, *bio.Reader, string, int64, string)
-	pkg    string
-	pn     string
-	file   string
-	off    int64
-	length int64
-}
-
-var hostobj []Hostobj
-
-// These packages can use internal linking mode.
-// Others trigger external mode.
-var internalpkg = []string{
-	"crypto/x509",
-	"net",
-	"os/user",
-	"runtime/cgo",
-	"runtime/race",
-	"runtime/msan",
-}
-
-func ldhostobj(ld func(*Link, *bio.Reader, string, int64, string), headType objabi.HeadType, f *bio.Reader, pkg string, length int64, pn string, file string) *Hostobj {
-	isinternal := false
-	for _, intpkg := range internalpkg {
-		if pkg == intpkg {
-			isinternal = true
-			break
-		}
-	}
-
-	// DragonFly declares errno with __thread, which results in a symbol
-	// type of R_386_TLS_GD or R_X86_64_TLSGD. The Go linker does not
-	// currently know how to handle TLS relocations, hence we have to
-	// force external linking for any libraries that link in code that
-	// uses errno. This can be removed if the Go linker ever supports
-	// these relocation types.
-	if headType == objabi.Hdragonfly {
-		if pkg == "net" || pkg == "os/user" {
-			isinternal = false
-		}
-	}
-
-	if !isinternal {
-		externalobj = true
-	}
-
-	hostobj = append(hostobj, Hostobj{})
-	h := &hostobj[len(hostobj)-1]
-	h.ld = ld
-	h.pkg = pkg
-	h.pn = pn
-	h.file = file
-	h.off = f.Offset()
-	h.length = length
-	return h
-}
-
-func hostobjs(ctxt *Link) {
-	if ctxt.LinkMode != LinkInternal {
-		return
-	}
-	var h *Hostobj
-
-	for i := 0; i < len(hostobj); i++ {
-		h = &hostobj[i]
-		f, err := bio.Open(h.file)
-		if err != nil {
-			Exitf("cannot reopen %s: %v", h.pn, err)
-		}
-
-		f.MustSeek(h.off, 0)
-		h.ld(ctxt, f, h.pkg, h.length, h.pn)
-		f.Close()
-	}
-}
-
-func hostlinksetup(ctxt *Link) {
-	if ctxt.LinkMode != LinkExternal {
-		return
-	}
-
-	// For external link, record that we need to tell the external linker -s,
-	// and turn off -s internally: the external linker needs the symbol
-	// information for its final link.
-	debug_s = *FlagS
-	*FlagS = false
-
-	// create temporary directory and arrange cleanup
-	if *flagTmpdir == "" {
-		dir, err := ioutil.TempDir("", "go-link-")
-		if err != nil {
-			log.Fatal(err)
-		}
-		*flagTmpdir = dir
-		ownTmpDir = true
-		AtExit(func() {
-			ctxt.Out.f.Close()
-			os.RemoveAll(*flagTmpdir)
-		})
-	}
-
-	// change our output to temporary object file
-	ctxt.Out.f.Close()
-	mayberemoveoutfile()
-
-	p := filepath.Join(*flagTmpdir, "go.o")
-	var err error
-	f, err := os.OpenFile(p, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0775)
-	if err != nil {
-		Exitf("cannot create %s: %v", p, err)
-	}
-
-	ctxt.Out.w = bufio.NewWriter(f)
-	ctxt.Out.f = f
-	ctxt.Out.off = 0
-}
-
-// hostobjCopy creates a copy of the object files in hostobj in a
-// temporary directory.
-func hostobjCopy() (paths []string) {
-	var wg sync.WaitGroup
-	sema := make(chan struct{}, runtime.NumCPU()) // limit open file descriptors
-	for i, h := range hostobj {
-		h := h
-		dst := filepath.Join(*flagTmpdir, fmt.Sprintf("%06d.o", i))
-		paths = append(paths, dst)
-
-		wg.Add(1)
-		go func() {
-			sema <- struct{}{}
-			defer func() {
-				<-sema
-				wg.Done()
-			}()
-			f, err := os.Open(h.file)
-			if err != nil {
-				Exitf("cannot reopen %s: %v", h.pn, err)
-			}
-			defer f.Close()
-			if _, err := f.Seek(h.off, 0); err != nil {
-				Exitf("cannot seek %s: %v", h.pn, err)
-			}
-
-			w, err := os.Create(dst)
-			if err != nil {
-				Exitf("cannot create %s: %v", dst, err)
-			}
-			if _, err := io.CopyN(w, f, h.length); err != nil {
-				Exitf("cannot write %s: %v", dst, err)
-			}
-			if err := w.Close(); err != nil {
-				Exitf("cannot close %s: %v", dst, err)
-			}
-		}()
-	}
-	wg.Wait()
-	return paths
-}
-
-// writeGDBLinkerScript creates gcc linker script file in temp
-// directory. writeGDBLinkerScript returns created file path.
-// The script is used to work around gcc bug
-// (see https://golang.org/issue/20183 for details).
-func writeGDBLinkerScript() string {
-	name := "fix_debug_gdb_scripts.ld"
-	path := filepath.Join(*flagTmpdir, name)
-	src := `SECTIONS
-{
-  .debug_gdb_scripts BLOCK(__section_alignment__) (NOLOAD) :
-  {
-    *(.debug_gdb_scripts)
-  }
-}
-INSERT AFTER .debug_types;
-`
-	err := ioutil.WriteFile(path, []byte(src), 0666)
-	if err != nil {
-		Errorf(nil, "WriteFile %s failed: %v", name, err)
-	}
-	return path
-}
-
-// archive builds a .a archive from the hostobj object files.
-func (ctxt *Link) archive() {
-	if ctxt.BuildMode != BuildModeCArchive {
-		return
-	}
-
-	exitIfErrors()
-
-	if *flagExtar == "" {
-		*flagExtar = "ar"
-	}
-
-	mayberemoveoutfile()
-
-	// Force the buffer to flush here so that external
-	// tools will see a complete file.
-	ctxt.Out.Flush()
-	if err := ctxt.Out.f.Close(); err != nil {
-		Exitf("close: %v", err)
-	}
-	ctxt.Out.f = nil
-
-	argv := []string{*flagExtar, "-q", "-c", "-s"}
-	if ctxt.HeadType == objabi.Haix {
-		argv = append(argv, "-X64")
-	}
-	argv = append(argv, *flagOutfile)
-	argv = append(argv, filepath.Join(*flagTmpdir, "go.o"))
-	argv = append(argv, hostobjCopy()...)
-
-	if ctxt.Debugvlog != 0 {
-		ctxt.Logf("archive: %s\n", strings.Join(argv, " "))
-	}
-
-	// If supported, use syscall.Exec() to invoke the archive command,
-	// which should be the final remaining step needed for the link.
-	// This will reduce peak RSS for the link (and speed up linking of
-	// large applications), since when the archive command runs we
-	// won't be holding onto all of the linker's live memory.
-	if syscallExecSupported && !ownTmpDir {
-		runAtExitFuncs()
-		ctxt.execArchive(argv)
-		panic("should not get here")
-	}
-
-	// Otherwise invoke 'ar' in the usual way (fork + exec).
-	if out, err := exec.Command(argv[0], argv[1:]...).CombinedOutput(); err != nil {
-		Exitf("running %s failed: %v\n%s", argv[0], err, out)
-	}
-}
-
-func (ctxt *Link) hostlink() {
-	if ctxt.LinkMode != LinkExternal || nerrors > 0 {
-		return
-	}
-	if ctxt.BuildMode == BuildModeCArchive {
-		return
-	}
-
-	var argv []string
-	argv = append(argv, ctxt.extld())
-	argv = append(argv, hostlinkArchArgs(ctxt.Arch)...)
-
-	if *FlagS || debug_s {
-		if ctxt.HeadType == objabi.Hdarwin {
-			// Recent versions of macOS print
-			//	ld: warning: option -s is obsolete and being ignored
-			// so do not pass any arguments.
-		} else {
-			argv = append(argv, "-s")
-		}
-	}
-
-	switch ctxt.HeadType {
-	case objabi.Hdarwin:
-		if machoPlatform == PLATFORM_MACOS {
-			// -headerpad is incompatible with -fembed-bitcode.
-			argv = append(argv, "-Wl,-headerpad,1144")
-		}
-		if ctxt.DynlinkingGo() && !ctxt.Arch.InFamily(sys.ARM, sys.ARM64) {
-			argv = append(argv, "-Wl,-flat_namespace")
-		}
-	case objabi.Hopenbsd:
-		argv = append(argv, "-Wl,-nopie")
-	case objabi.Hwindows:
-		if windowsgui {
-			argv = append(argv, "-mwindows")
-		} else {
-			argv = append(argv, "-mconsole")
-		}
-		// Mark as having awareness of terminal services, to avoid
-		// ancient compatibility hacks.
-		argv = append(argv, "-Wl,--tsaware")
-
-		// Enable DEP
-		argv = append(argv, "-Wl,--nxcompat")
-
-		argv = append(argv, fmt.Sprintf("-Wl,--major-os-version=%d", PeMinimumTargetMajorVersion))
-		argv = append(argv, fmt.Sprintf("-Wl,--minor-os-version=%d", PeMinimumTargetMinorVersion))
-		argv = append(argv, fmt.Sprintf("-Wl,--major-subsystem-version=%d", PeMinimumTargetMajorVersion))
-		argv = append(argv, fmt.Sprintf("-Wl,--minor-subsystem-version=%d", PeMinimumTargetMinorVersion))
-	case objabi.Haix:
-		argv = append(argv, "-pthread")
-		// prevent ld to reorder .text functions to keep the same
-		// first/last functions for moduledata.
-		argv = append(argv, "-Wl,-bnoobjreorder")
-		// mcmodel=large is needed for every gcc generated files, but
-		// ld still need -bbigtoc in order to allow larger TOC.
-		argv = append(argv, "-mcmodel=large")
-		argv = append(argv, "-Wl,-bbigtoc")
-	}
-
-	switch ctxt.BuildMode {
-	case BuildModeExe:
-		if ctxt.HeadType == objabi.Hdarwin {
-			if machoPlatform == PLATFORM_MACOS {
-				argv = append(argv, "-Wl,-no_pie")
-				argv = append(argv, "-Wl,-pagezero_size,4000000")
-			}
-		}
-	case BuildModePIE:
-		switch ctxt.HeadType {
-		case objabi.Hdarwin, objabi.Haix:
-		case objabi.Hwindows:
-			// Enable ASLR.
-			argv = append(argv, "-Wl,--dynamicbase")
-			// enable high-entropy ASLR on 64-bit.
-			if ctxt.Arch.PtrSize >= 8 {
-				argv = append(argv, "-Wl,--high-entropy-va")
-			}
-			// Work around binutils limitation that strips relocation table for dynamicbase.
-			// See https://sourceware.org/bugzilla/show_bug.cgi?id=19011
-			argv = append(argv, "-Wl,--export-all-symbols")
-		default:
-			// ELF.
-			if ctxt.UseRelro() {
-				argv = append(argv, "-Wl,-z,relro")
-			}
-			argv = append(argv, "-pie")
-		}
-	case BuildModeCShared:
-		if ctxt.HeadType == objabi.Hdarwin {
-			argv = append(argv, "-dynamiclib")
-			if ctxt.Arch.Family != sys.AMD64 {
-				argv = append(argv, "-Wl,-read_only_relocs,suppress")
-			}
-		} else {
-			// ELF.
-			argv = append(argv, "-Wl,-Bsymbolic")
-			if ctxt.UseRelro() {
-				argv = append(argv, "-Wl,-z,relro")
-			}
-			argv = append(argv, "-shared")
-			if ctxt.HeadType != objabi.Hwindows {
-				// Pass -z nodelete to mark the shared library as
-				// non-closeable: a dlclose will do nothing.
-				argv = append(argv, "-Wl,-z,nodelete")
-			}
-		}
-	case BuildModeShared:
-		if ctxt.UseRelro() {
-			argv = append(argv, "-Wl,-z,relro")
-		}
-		argv = append(argv, "-shared")
-	case BuildModePlugin:
-		if ctxt.HeadType == objabi.Hdarwin {
-			argv = append(argv, "-dynamiclib")
-		} else {
-			if ctxt.UseRelro() {
-				argv = append(argv, "-Wl,-z,relro")
-			}
-			argv = append(argv, "-shared")
-		}
-	}
-
-	if ctxt.IsELF && ctxt.DynlinkingGo() {
-		// We force all symbol resolution to be done at program startup
-		// because lazy PLT resolution can use large amounts of stack at
-		// times we cannot allow it to do so.
-		argv = append(argv, "-Wl,-znow")
-
-		// Do not let the host linker generate COPY relocations. These
-		// can move symbols out of sections that rely on stable offsets
-		// from the beginning of the section (like sym.STYPE).
-		argv = append(argv, "-Wl,-znocopyreloc")
-
-		if ctxt.Arch.InFamily(sys.ARM, sys.ARM64) && objabi.GOOS == "linux" {
-			// On ARM, the GNU linker will generate COPY relocations
-			// even with -znocopyreloc set.
-			// https://sourceware.org/bugzilla/show_bug.cgi?id=19962
-			//
-			// On ARM64, the GNU linker will fail instead of
-			// generating COPY relocations.
-			//
-			// In both cases, switch to gold.
-			argv = append(argv, "-fuse-ld=gold")
-
-			// If gold is not installed, gcc will silently switch
-			// back to ld.bfd. So we parse the version information
-			// and provide a useful error if gold is missing.
-			cmd := exec.Command(*flagExtld, "-fuse-ld=gold", "-Wl,--version")
-			if out, err := cmd.CombinedOutput(); err == nil {
-				if !bytes.Contains(out, []byte("GNU gold")) {
-					log.Fatalf("ARM external linker must be gold (issue #15696), but is not: %s", out)
-				}
-			}
-		}
-	}
-
-	if ctxt.Arch.Family == sys.ARM64 && objabi.GOOS == "freebsd" {
-		// Switch to ld.bfd on freebsd/arm64.
-		argv = append(argv, "-fuse-ld=bfd")
-
-		// Provide a useful error if ld.bfd is missing.
-		cmd := exec.Command(*flagExtld, "-fuse-ld=bfd", "-Wl,--version")
-		if out, err := cmd.CombinedOutput(); err == nil {
-			if !bytes.Contains(out, []byte("GNU ld")) {
-				log.Fatalf("ARM64 external linker must be ld.bfd (issue #35197), please install devel/binutils")
-			}
-		}
-	}
-
-	if ctxt.IsELF && len(buildinfo) > 0 {
-		argv = append(argv, fmt.Sprintf("-Wl,--build-id=0x%x", buildinfo))
-	}
-
-	// On Windows, given -o foo, GCC will append ".exe" to produce
-	// "foo.exe".  We have decided that we want to honor the -o
-	// option. To make this work, we append a '.' so that GCC
-	// will decide that the file already has an extension. We
-	// only want to do this when producing a Windows output file
-	// on a Windows host.
-	outopt := *flagOutfile
-	if objabi.GOOS == "windows" && runtime.GOOS == "windows" && filepath.Ext(outopt) == "" {
-		outopt += "."
-	}
-	argv = append(argv, "-o")
-	argv = append(argv, outopt)
-
-	if rpath.val != "" {
-		argv = append(argv, fmt.Sprintf("-Wl,-rpath,%s", rpath.val))
-	}
-
-	// Force global symbols to be exported for dlopen, etc.
-	if ctxt.IsELF {
-		argv = append(argv, "-rdynamic")
-	}
-	if ctxt.HeadType == objabi.Haix {
-		fileName := xcoffCreateExportFile(ctxt)
-		argv = append(argv, "-Wl,-bE:"+fileName)
-	}
-
-	if strings.Contains(argv[0], "clang") {
-		argv = append(argv, "-Qunused-arguments")
-	}
-
-	const compressDWARF = "-Wl,--compress-debug-sections=zlib-gnu"
-	if ctxt.compressDWARF && linkerFlagSupported(argv[0], compressDWARF) {
-		argv = append(argv, compressDWARF)
-	}
-
-	argv = append(argv, filepath.Join(*flagTmpdir, "go.o"))
-	argv = append(argv, hostobjCopy()...)
-	if ctxt.HeadType == objabi.Haix {
-		// We want to have C files after Go files to remove
-		// trampolines csects made by ld.
-		argv = append(argv, "-nostartfiles")
-		argv = append(argv, "/lib/crt0_64.o")
-
-		extld := ctxt.extld()
-		// Get starting files.
-		getPathFile := func(file string) string {
-			args := []string{"-maix64", "--print-file-name=" + file}
-			out, err := exec.Command(extld, args...).CombinedOutput()
-			if err != nil {
-				log.Fatalf("running %s failed: %v\n%s", extld, err, out)
-			}
-			return strings.Trim(string(out), "\n")
-		}
-		argv = append(argv, getPathFile("crtcxa.o"))
-		argv = append(argv, getPathFile("crtdbase.o"))
-	}
-
-	if ctxt.linkShared {
-		seenDirs := make(map[string]bool)
-		seenLibs := make(map[string]bool)
-		addshlib := func(path string) {
-			dir, base := filepath.Split(path)
-			if !seenDirs[dir] {
-				argv = append(argv, "-L"+dir)
-				if !rpath.set {
-					argv = append(argv, "-Wl,-rpath="+dir)
-				}
-				seenDirs[dir] = true
-			}
-			base = strings.TrimSuffix(base, ".so")
-			base = strings.TrimPrefix(base, "lib")
-			if !seenLibs[base] {
-				argv = append(argv, "-l"+base)
-				seenLibs[base] = true
-			}
-		}
-		for _, shlib := range ctxt.Shlibs {
-			addshlib(shlib.Path)
-			for _, dep := range shlib.Deps {
-				if dep == "" {
-					continue
-				}
-				libpath := findshlib(ctxt, dep)
-				if libpath != "" {
-					addshlib(libpath)
-				}
-			}
-		}
-	}
-
-	// clang, unlike GCC, passes -rdynamic to the linker
-	// even when linking with -static, causing a linker
-	// error when using GNU ld. So take out -rdynamic if
-	// we added it. We do it in this order, rather than
-	// only adding -rdynamic later, so that -*extldflags
-	// can override -rdynamic without using -static.
-	checkStatic := func(arg string) {
-		if ctxt.IsELF && arg == "-static" {
-			for i := range argv {
-				if argv[i] == "-rdynamic" {
-					argv[i] = "-static"
-				}
-			}
-		}
-	}
-
-	for _, p := range ldflag {
-		argv = append(argv, p)
-		checkStatic(p)
-	}
-
-	// When building a program with the default -buildmode=exe the
-	// gc compiler generates code requires DT_TEXTREL in a
-	// position independent executable (PIE). On systems where the
-	// toolchain creates PIEs by default, and where DT_TEXTREL
-	// does not work, the resulting programs will not run. See
-	// issue #17847. To avoid this problem pass -no-pie to the
-	// toolchain if it is supported.
-	if ctxt.BuildMode == BuildModeExe && !ctxt.linkShared {
-		// GCC uses -no-pie, clang uses -nopie.
-		for _, nopie := range []string{"-no-pie", "-nopie"} {
-			if linkerFlagSupported(argv[0], nopie) {
-				argv = append(argv, nopie)
-				break
-			}
-		}
-	}
-
-	for _, p := range strings.Fields(*flagExtldflags) {
-		argv = append(argv, p)
-		checkStatic(p)
-	}
-	if ctxt.HeadType == objabi.Hwindows {
-		// use gcc linker script to work around gcc bug
-		// (see https://golang.org/issue/20183 for details).
-		p := writeGDBLinkerScript()
-		argv = append(argv, "-Wl,-T,"+p)
-		// libmingw32 and libmingwex have some inter-dependencies,
-		// so must use linker groups.
-		argv = append(argv, "-Wl,--start-group", "-lmingwex", "-lmingw32", "-Wl,--end-group")
-		argv = append(argv, peimporteddlls()...)
-	}
-
-	if ctxt.Debugvlog != 0 {
-		ctxt.Logf("host link:")
-		for _, v := range argv {
-			ctxt.Logf(" %q", v)
-		}
-		ctxt.Logf("\n")
-	}
-
-	out, err := exec.Command(argv[0], argv[1:]...).CombinedOutput()
-	if err != nil {
-		Exitf("running %s failed: %v\n%s", argv[0], err, out)
-	}
-
-	// Filter out useless linker warnings caused by bugs outside Go.
-	// See also cmd/go/internal/work/exec.go's gccld method.
-	var save [][]byte
-	var skipLines int
-	for _, line := range bytes.SplitAfter(out, []byte("\n")) {
-		// golang.org/issue/26073 - Apple Xcode bug
-		if bytes.Contains(line, []byte("ld: warning: text-based stub file")) {
-			continue
-		}
-
-		if skipLines > 0 {
-			skipLines--
-			continue
-		}
-
-		// Remove TOC overflow warning on AIX.
-		if bytes.Contains(line, []byte("ld: 0711-783")) {
-			skipLines = 2
-			continue
-		}
-
-		save = append(save, line)
-	}
-	out = bytes.Join(save, nil)
-
-	if len(out) > 0 {
-		// always print external output even if the command is successful, so that we don't
-		// swallow linker warnings (see https://golang.org/issue/17935).
-		ctxt.Logf("%s", out)
-	}
-
-	if !*FlagS && !*FlagW && !debug_s && ctxt.HeadType == objabi.Hdarwin {
-		dsym := filepath.Join(*flagTmpdir, "go.dwarf")
-		if out, err := exec.Command("dsymutil", "-f", *flagOutfile, "-o", dsym).CombinedOutput(); err != nil {
-			Exitf("%s: running dsymutil failed: %v\n%s", os.Args[0], err, out)
-		}
-		// Skip combining if `dsymutil` didn't generate a file. See #11994.
-		if _, err := os.Stat(dsym); os.IsNotExist(err) {
-			return
-		}
-		// For os.Rename to work reliably, must be in same directory as outfile.
-		combinedOutput := *flagOutfile + "~"
-		exef, err := os.Open(*flagOutfile)
-		if err != nil {
-			Exitf("%s: combining dwarf failed: %v", os.Args[0], err)
-		}
-		defer exef.Close()
-		exem, err := macho.NewFile(exef)
-		if err != nil {
-			Exitf("%s: parsing Mach-O header failed: %v", os.Args[0], err)
-		}
-		// Only macOS supports unmapped segments such as our __DWARF segment.
-		if machoPlatform == PLATFORM_MACOS {
-			if err := machoCombineDwarf(ctxt, exef, exem, dsym, combinedOutput); err != nil {
-				Exitf("%s: combining dwarf failed: %v", os.Args[0], err)
-			}
-			os.Remove(*flagOutfile)
-			if err := os.Rename(combinedOutput, *flagOutfile); err != nil {
-				Exitf("%s: %v", os.Args[0], err)
-			}
-		}
-	}
-}
-
-var createTrivialCOnce sync.Once
-
-func linkerFlagSupported(linker, flag string) bool {
-	createTrivialCOnce.Do(func() {
-		src := filepath.Join(*flagTmpdir, "trivial.c")
-		if err := ioutil.WriteFile(src, []byte("int main() { return 0; }"), 0666); err != nil {
-			Errorf(nil, "WriteFile trivial.c failed: %v", err)
-		}
-	})
-
-	flagsWithNextArgSkip := []string{
-		"-F",
-		"-l",
-		"-L",
-		"-framework",
-		"-Wl,-framework",
-		"-Wl,-rpath",
-		"-Wl,-undefined",
-	}
-	flagsWithNextArgKeep := []string{
-		"-arch",
-		"-isysroot",
-		"--sysroot",
-		"-target",
-	}
-	prefixesToKeep := []string{
-		"-f",
-		"-m",
-		"-p",
-		"-Wl,",
-		"-arch",
-		"-isysroot",
-		"--sysroot",
-		"-target",
-	}
-
-	var flags []string
-	keep := false
-	skip := false
-	extldflags := strings.Fields(*flagExtldflags)
-	for _, f := range append(extldflags, ldflag...) {
-		if keep {
-			flags = append(flags, f)
-			keep = false
-		} else if skip {
-			skip = false
-		} else if f == "" || f[0] != '-' {
-		} else if contains(flagsWithNextArgSkip, f) {
-			skip = true
-		} else if contains(flagsWithNextArgKeep, f) {
-			flags = append(flags, f)
-			keep = true
-		} else {
-			for _, p := range prefixesToKeep {
-				if strings.HasPrefix(f, p) {
-					flags = append(flags, f)
-					break
-				}
-			}
-		}
-	}
-
-	flags = append(flags, flag, "trivial.c")
-
-	cmd := exec.Command(linker, flags...)
-	cmd.Dir = *flagTmpdir
-	cmd.Env = append([]string{"LC_ALL=C"}, os.Environ()...)
-	out, err := cmd.CombinedOutput()
-	// GCC says "unrecognized command line option ‘-no-pie’"
-	// clang says "unknown argument: '-no-pie'"
-	return err == nil && !bytes.Contains(out, []byte("unrecognized")) && !bytes.Contains(out, []byte("unknown"))
-}
-
-// hostlinkArchArgs returns arguments to pass to the external linker
-// based on the architecture.
-func hostlinkArchArgs(arch *sys.Arch) []string {
-	switch arch.Family {
-	case sys.I386:
-		return []string{"-m32"}
-	case sys.AMD64, sys.S390X:
-		return []string{"-m64"}
-	case sys.ARM:
-		return []string{"-marm"}
-	case sys.ARM64:
-		// nothing needed
-	case sys.MIPS64:
-		return []string{"-mabi=64"}
-	case sys.MIPS:
-		return []string{"-mabi=32"}
-	case sys.PPC64:
-		if objabi.GOOS == "aix" {
-			return []string{"-maix64"}
-		} else {
-			return []string{"-m64"}
-		}
-
-	}
-	return nil
-}
-
-// ldobj loads an input object. If it is a host object (an object
-// compiled by a non-Go compiler) it returns the Hostobj pointer. If
-// it is a Go object, it returns nil.
-func ldobj(ctxt *Link, f *bio.Reader, lib *sym.Library, length int64, pn string, file string) *Hostobj {
-	pkg := objabi.PathToPrefix(lib.Pkg)
-
-	eof := f.Offset() + length
-	start := f.Offset()
-	c1 := bgetc(f)
-	c2 := bgetc(f)
-	c3 := bgetc(f)
-	c4 := bgetc(f)
-	f.MustSeek(start, 0)
-
-	unit := &sym.CompilationUnit{Lib: lib}
-	lib.Units = append(lib.Units, unit)
-
-	magic := uint32(c1)<<24 | uint32(c2)<<16 | uint32(c3)<<8 | uint32(c4)
-	if magic == 0x7f454c46 { // \x7F E L F
-		if *flagNewobj {
-			ldelf := func(ctxt *Link, f *bio.Reader, pkg string, length int64, pn string) {
-				textp, flags, err := loadelf.Load(ctxt.loader, ctxt.Arch, ctxt.Syms, f, pkg, length, pn, ehdr.flags)
-				if err != nil {
-					Errorf(nil, "%v", err)
-					return
-				}
-				ehdr.flags = flags
-				ctxt.Textp = append(ctxt.Textp, textp...)
-			}
-			return ldhostobj(ldelf, ctxt.HeadType, f, pkg, length, pn, file)
-		} else {
-			ldelf := func(ctxt *Link, f *bio.Reader, pkg string, length int64, pn string) {
-				textp, flags, err := loadelf.LoadOld(ctxt.Arch, ctxt.Syms, f, pkg, length, pn, ehdr.flags)
-				if err != nil {
-					Errorf(nil, "%v", err)
-					return
-				}
-				ehdr.flags = flags
-				ctxt.Textp = append(ctxt.Textp, textp...)
-			}
-			return ldhostobj(ldelf, ctxt.HeadType, f, pkg, length, pn, file)
-		}
-	}
-
-	if magic&^1 == 0xfeedface || magic&^0x01000000 == 0xcefaedfe {
-		if *flagNewobj {
-			ldmacho := func(ctxt *Link, f *bio.Reader, pkg string, length int64, pn string) {
-				textp, err := loadmacho.Load(ctxt.loader, ctxt.Arch, ctxt.Syms, f, pkg, length, pn)
-				if err != nil {
-					Errorf(nil, "%v", err)
-					return
-				}
-				ctxt.Textp = append(ctxt.Textp, textp...)
-			}
-			return ldhostobj(ldmacho, ctxt.HeadType, f, pkg, length, pn, file)
-		} else {
-			ldmacho := func(ctxt *Link, f *bio.Reader, pkg string, length int64, pn string) {
-				textp, err := loadmacho.LoadOld(ctxt.Arch, ctxt.Syms, f, pkg, length, pn)
-				if err != nil {
-					Errorf(nil, "%v", err)
-					return
-				}
-				ctxt.Textp = append(ctxt.Textp, textp...)
-			}
-			return ldhostobj(ldmacho, ctxt.HeadType, f, pkg, length, pn, file)
-		}
-	}
-
-	if c1 == 0x4c && c2 == 0x01 || c1 == 0x64 && c2 == 0x86 {
-		if *flagNewobj {
-			ldpe := func(ctxt *Link, f *bio.Reader, pkg string, length int64, pn string) {
-				textp, rsrc, err := loadpe.Load(ctxt.loader, ctxt.Arch, ctxt.Syms, f, pkg, length, pn)
-				if err != nil {
-					Errorf(nil, "%v", err)
-					return
-				}
-				if rsrc != nil {
-					setpersrc(ctxt, rsrc)
-				}
-				ctxt.Textp = append(ctxt.Textp, textp...)
-			}
-			return ldhostobj(ldpe, ctxt.HeadType, f, pkg, length, pn, file)
-		} else {
-			ldpe := func(ctxt *Link, f *bio.Reader, pkg string, length int64, pn string) {
-				textp, rsrc, err := loadpe.LoadOld(ctxt.Arch, ctxt.Syms, f, pkg, length, pn)
-				if err != nil {
-					Errorf(nil, "%v", err)
-					return
-				}
-				if rsrc != nil {
-					setpersrc(ctxt, rsrc)
-				}
-				ctxt.Textp = append(ctxt.Textp, textp...)
-			}
-			return ldhostobj(ldpe, ctxt.HeadType, f, pkg, length, pn, file)
-		}
-	}
-
-	if c1 == 0x01 && (c2 == 0xD7 || c2 == 0xF7) {
-		if *flagNewobj {
-			ldxcoff := func(ctxt *Link, f *bio.Reader, pkg string, length int64, pn string) {
-				textp, err := loadxcoff.Load(ctxt.loader, ctxt.Arch, ctxt.Syms, f, pkg, length, pn)
-				if err != nil {
-					Errorf(nil, "%v", err)
-					return
-				}
-				ctxt.Textp = append(ctxt.Textp, textp...)
-			}
-			return ldhostobj(ldxcoff, ctxt.HeadType, f, pkg, length, pn, file)
-		} else {
-			ldxcoff := func(ctxt *Link, f *bio.Reader, pkg string, length int64, pn string) {
-				textp, err := loadxcoff.LoadOld(ctxt.Arch, ctxt.Syms, f, pkg, length, pn)
-				if err != nil {
-					Errorf(nil, "%v", err)
-					return
-				}
-				ctxt.Textp = append(ctxt.Textp, textp...)
-			}
-			return ldhostobj(ldxcoff, ctxt.HeadType, f, pkg, length, pn, file)
-		}
-	}
-
-	/* check the header */
-	line, err := f.ReadString('\n')
-	if err != nil {
-		Errorf(nil, "truncated object file: %s: %v", pn, err)
-		return nil
-	}
-
-	if !strings.HasPrefix(line, "go object ") {
-		if strings.HasSuffix(pn, ".go") {
-			Exitf("%s: uncompiled .go source file", pn)
-			return nil
-		}
-
-		if line == ctxt.Arch.Name {
-			// old header format: just $GOOS
-			Errorf(nil, "%s: stale object file", pn)
-			return nil
-		}
-
-		Errorf(nil, "%s: not an object file", pn)
-		return nil
-	}
-
-	// First, check that the basic GOOS, GOARCH, and Version match.
-	t := fmt.Sprintf("%s %s %s ", objabi.GOOS, objabi.GOARCH, objabi.Version)
-
-	line = strings.TrimRight(line, "\n")
-	if !strings.HasPrefix(line[10:]+" ", t) && !*flagF {
-		Errorf(nil, "%s: object is [%s] expected [%s]", pn, line[10:], t)
-		return nil
-	}
-
-	// Second, check that longer lines match each other exactly,
-	// so that the Go compiler and write additional information
-	// that must be the same from run to run.
-	if len(line) >= len(t)+10 {
-		if theline == "" {
-			theline = line[10:]
-		} else if theline != line[10:] {
-			Errorf(nil, "%s: object is [%s] expected [%s]", pn, line[10:], theline)
-			return nil
-		}
-	}
-
-	// Skip over exports and other info -- ends with \n!\n.
-	//
-	// Note: It's possible for "\n!\n" to appear within the binary
-	// package export data format. To avoid truncating the package
-	// definition prematurely (issue 21703), we keep track of
-	// how many "$$" delimiters we've seen.
-
-	import0 := f.Offset()
-
-	c1 = '\n' // the last line ended in \n
-	c2 = bgetc(f)
-	c3 = bgetc(f)
-	markers := 0
-	for {
-		if c1 == '\n' {
-			if markers%2 == 0 && c2 == '!' && c3 == '\n' {
-				break
-			}
-			if c2 == '$' && c3 == '$' {
-				markers++
-			}
-		}
-
-		c1 = c2
-		c2 = c3
-		c3 = bgetc(f)
-		if c3 == -1 {
-			Errorf(nil, "truncated object file: %s", pn)
-			return nil
-		}
-	}
-
-	import1 := f.Offset()
-
-	f.MustSeek(import0, 0)
-	ldpkg(ctxt, f, lib, import1-import0-2, pn) // -2 for !\n
-	f.MustSeek(import1, 0)
-
-	flags := 0
-	switch *FlagStrictDups {
-	case 0:
-		break
-	case 1:
-		flags = objfile.StrictDupsWarnFlag
-	case 2:
-		flags = objfile.StrictDupsErrFlag
-	default:
-		log.Fatalf("invalid -strictdups flag value %d", *FlagStrictDups)
-	}
-	var c int
-	if *flagNewobj {
-		ctxt.loader.Preload(ctxt.Arch, ctxt.Syms, f, lib, unit, eof-f.Offset(), pn, flags)
-	} else {
-		c = objfile.Load(ctxt.Arch, ctxt.Syms, f, lib, unit, eof-f.Offset(), pn, flags)
-	}
-	strictDupMsgCount += c
-	addImports(ctxt, lib, pn)
-	return nil
-}
-
-func readelfsymboldata(ctxt *Link, f *elf.File, sym *elf.Symbol) []byte {
-	data := make([]byte, sym.Size)
-	sect := f.Sections[sym.Section]
-	if sect.Type != elf.SHT_PROGBITS && sect.Type != elf.SHT_NOTE {
-		Errorf(nil, "reading %s from non-data section", sym.Name)
-	}
-	n, err := sect.ReadAt(data, int64(sym.Value-sect.Addr))
-	if uint64(n) != sym.Size {
-		Errorf(nil, "reading contents of %s: %v", sym.Name, err)
-	}
-	return data
-}
-
-func readwithpad(r io.Reader, sz int32) ([]byte, error) {
-	data := make([]byte, Rnd(int64(sz), 4))
-	_, err := io.ReadFull(r, data)
-	if err != nil {
-		return nil, err
-	}
-	data = data[:sz]
-	return data, nil
-}
-
-func readnote(f *elf.File, name []byte, typ int32) ([]byte, error) {
-	for _, sect := range f.Sections {
-		if sect.Type != elf.SHT_NOTE {
-			continue
-		}
-		r := sect.Open()
-		for {
-			var namesize, descsize, noteType int32
-			err := binary.Read(r, f.ByteOrder, &namesize)
-			if err != nil {
-				if err == io.EOF {
-					break
-				}
-				return nil, fmt.Errorf("read namesize failed: %v", err)
-			}
-			err = binary.Read(r, f.ByteOrder, &descsize)
-			if err != nil {
-				return nil, fmt.Errorf("read descsize failed: %v", err)
-			}
-			err = binary.Read(r, f.ByteOrder, &noteType)
-			if err != nil {
-				return nil, fmt.Errorf("read type failed: %v", err)
-			}
-			noteName, err := readwithpad(r, namesize)
-			if err != nil {
-				return nil, fmt.Errorf("read name failed: %v", err)
-			}
-			desc, err := readwithpad(r, descsize)
-			if err != nil {
-				return nil, fmt.Errorf("read desc failed: %v", err)
-			}
-			if string(name) == string(noteName) && typ == noteType {
-				return desc, nil
-			}
-		}
-	}
-	return nil, nil
-}
-
-func findshlib(ctxt *Link, shlib string) string {
-	if filepath.IsAbs(shlib) {
-		return shlib
-	}
-	for _, libdir := range ctxt.Libdir {
-		libpath := filepath.Join(libdir, shlib)
-		if _, err := os.Stat(libpath); err == nil {
-			return libpath
-		}
-	}
-	Errorf(nil, "cannot find shared library: %s", shlib)
-	return ""
-}
-
-func ldshlibsyms(ctxt *Link, shlib string) {
-	var libpath string
-	if filepath.IsAbs(shlib) {
-		libpath = shlib
-		shlib = filepath.Base(shlib)
-	} else {
-		libpath = findshlib(ctxt, shlib)
-		if libpath == "" {
-			return
-		}
-	}
-	for _, processedlib := range ctxt.Shlibs {
-		if processedlib.Path == libpath {
-			return
-		}
-	}
-	if ctxt.Debugvlog > 1 {
-		ctxt.Logf("ldshlibsyms: found library with name %s at %s\n", shlib, libpath)
-	}
-
-	f, err := elf.Open(libpath)
-	if err != nil {
-		Errorf(nil, "cannot open shared library: %s", libpath)
-		return
-	}
-	defer f.Close()
-
-	hash, err := readnote(f, ELF_NOTE_GO_NAME, ELF_NOTE_GOABIHASH_TAG)
-	if err != nil {
-		Errorf(nil, "cannot read ABI hash from shared library %s: %v", libpath, err)
-		return
-	}
-
-	depsbytes, err := readnote(f, ELF_NOTE_GO_NAME, ELF_NOTE_GODEPS_TAG)
-	if err != nil {
-		Errorf(nil, "cannot read dep list from shared library %s: %v", libpath, err)
-		return
-	}
-	var deps []string
-	for _, dep := range strings.Split(string(depsbytes), "\n") {
-		if dep == "" {
-			continue
-		}
-		if !filepath.IsAbs(dep) {
-			// If the dep can be interpreted as a path relative to the shlib
-			// in which it was found, do that. Otherwise, we will leave it
-			// to be resolved by libdir lookup.
-			abs := filepath.Join(filepath.Dir(libpath), dep)
-			if _, err := os.Stat(abs); err == nil {
-				dep = abs
-			}
-		}
-		deps = append(deps, dep)
-	}
-
-	syms, err := f.DynamicSymbols()
-	if err != nil {
-		Errorf(nil, "cannot read symbols from shared library: %s", libpath)
-		return
-	}
-	gcdataLocations := make(map[uint64]*sym.Symbol)
-	for _, elfsym := range syms {
-		if elf.ST_TYPE(elfsym.Info) == elf.STT_NOTYPE || elf.ST_TYPE(elfsym.Info) == elf.STT_SECTION {
-			continue
-		}
-
-		// Symbols whose names start with "type." are compiler
-		// generated, so make functions with that prefix internal.
-		ver := 0
-		if elf.ST_TYPE(elfsym.Info) == elf.STT_FUNC && strings.HasPrefix(elfsym.Name, "type.") {
-			ver = sym.SymVerABIInternal
-		}
-
-		var lsym *sym.Symbol
-		if *flagNewobj {
-			i := ctxt.loader.AddExtSym(elfsym.Name, ver)
-			if i == 0 {
-				continue
-			}
-			lsym = ctxt.Syms.Newsym(elfsym.Name, ver)
-			ctxt.loader.Syms[i] = lsym
-		} else {
-			lsym = ctxt.Syms.Lookup(elfsym.Name, ver)
-		}
-		// Because loadlib above loads all .a files before loading any shared
-		// libraries, any non-dynimport symbols we find that duplicate symbols
-		// already loaded should be ignored (the symbols from the .a files
-		// "win").
-		if lsym.Type != 0 && lsym.Type != sym.SDYNIMPORT {
-			continue
-		}
-		lsym.Type = sym.SDYNIMPORT
-		lsym.SetElfType(elf.ST_TYPE(elfsym.Info))
-		lsym.Size = int64(elfsym.Size)
-		if elfsym.Section != elf.SHN_UNDEF {
-			// Set .File for the library that actually defines the symbol.
-			lsym.File = libpath
-			// The decodetype_* functions in decodetype.go need access to
-			// the type data.
-			if strings.HasPrefix(lsym.Name, "type.") && !strings.HasPrefix(lsym.Name, "type..") {
-				lsym.P = readelfsymboldata(ctxt, f, &elfsym)
-				gcdataLocations[elfsym.Value+2*uint64(ctxt.Arch.PtrSize)+8+1*uint64(ctxt.Arch.PtrSize)] = lsym
-			}
-		}
-		// For function symbols, we don't know what ABI is
-		// available, so alias it under both ABIs.
-		//
-		// TODO(austin): This is almost certainly wrong once
-		// the ABIs are actually different. We might have to
-		// mangle Go function names in the .so to include the
-		// ABI.
-		if elf.ST_TYPE(elfsym.Info) == elf.STT_FUNC && ver == 0 {
-			var alias *sym.Symbol
-			if *flagNewobj {
-				i := ctxt.loader.AddExtSym(elfsym.Name, sym.SymVerABIInternal)
-				if i == 0 {
-					continue
-				}
-				alias = ctxt.Syms.Newsym(elfsym.Name, sym.SymVerABIInternal)
-				ctxt.loader.Syms[i] = alias
-			} else {
-				alias = ctxt.Syms.Lookup(elfsym.Name, sym.SymVerABIInternal)
-			}
-			if alias.Type != 0 {
-				continue
-			}
-			alias.Type = sym.SABIALIAS
-			alias.R = []sym.Reloc{{Sym: lsym}}
-		}
-	}
-	gcdataAddresses := make(map[*sym.Symbol]uint64)
-	if ctxt.Arch.Family == sys.ARM64 {
-		for _, sect := range f.Sections {
-			if sect.Type == elf.SHT_RELA {
-				var rela elf.Rela64
-				rdr := sect.Open()
-				for {
-					err := binary.Read(rdr, f.ByteOrder, &rela)
-					if err == io.EOF {
-						break
-					} else if err != nil {
-						Errorf(nil, "reading relocation failed %v", err)
-						return
-					}
-					t := elf.R_AARCH64(rela.Info & 0xffff)
-					if t != elf.R_AARCH64_RELATIVE {
-						continue
-					}
-					if lsym, ok := gcdataLocations[rela.Off]; ok {
-						gcdataAddresses[lsym] = uint64(rela.Addend)
-					}
-				}
-			}
-		}
-	}
-
-	ctxt.Shlibs = append(ctxt.Shlibs, Shlib{Path: libpath, Hash: hash, Deps: deps, File: f, gcdataAddresses: gcdataAddresses})
-}
-
-func addsection(arch *sys.Arch, seg *sym.Segment, name string, rwx int) *sym.Section {
-	sect := new(sym.Section)
-	sect.Rwx = uint8(rwx)
-	sect.Name = name
-	sect.Seg = seg
-	sect.Align = int32(arch.PtrSize) // everything is at least pointer-aligned
-	seg.Sections = append(seg.Sections, sect)
-	return sect
-}
-
-type chain struct {
-	sym   *sym.Symbol
-	up    *chain
-	limit int // limit on entry to sym
-}
-
-var morestack *sym.Symbol
-
-// TODO: Record enough information in new object files to
-// allow stack checks here.
-
-func haslinkregister(ctxt *Link) bool {
-	return ctxt.FixedFrameSize() != 0
-}
-
-func callsize(ctxt *Link) int {
-	if haslinkregister(ctxt) {
-		return 0
-	}
-	return ctxt.Arch.RegSize
-}
-
-func (ctxt *Link) dostkcheck() {
-	var ch chain
-
-	morestack = ctxt.Syms.Lookup("runtime.morestack", 0)
-
-	// Every splitting function ensures that there are at least StackLimit
-	// bytes available below SP when the splitting prologue finishes.
-	// If the splitting function calls F, then F begins execution with
-	// at least StackLimit - callsize() bytes available.
-	// Check that every function behaves correctly with this amount
-	// of stack, following direct calls in order to piece together chains
-	// of non-splitting functions.
-	ch.up = nil
-
-	ch.limit = objabi.StackLimit - callsize(ctxt)
-	if objabi.GOARCH == "arm64" {
-		// need extra 8 bytes below SP to save FP
-		ch.limit -= 8
-	}
-
-	// Check every function, but do the nosplit functions in a first pass,
-	// to make the printed failure chains as short as possible.
-	for _, s := range ctxt.Textp {
-		// runtime.racesymbolizethunk is called from gcc-compiled C
-		// code running on the operating system thread stack.
-		// It uses more than the usual amount of stack but that's okay.
-		if s.Name == "runtime.racesymbolizethunk" {
-			continue
-		}
-
-		if s.Attr.NoSplit() {
-			ch.sym = s
-			stkcheck(ctxt, &ch, 0)
-		}
-	}
-
-	for _, s := range ctxt.Textp {
-		if !s.Attr.NoSplit() {
-			ch.sym = s
-			stkcheck(ctxt, &ch, 0)
-		}
-	}
-}
-
-func stkcheck(ctxt *Link, up *chain, depth int) int {
-	limit := up.limit
-	s := up.sym
-
-	// Don't duplicate work: only need to consider each
-	// function at top of safe zone once.
-	top := limit == objabi.StackLimit-callsize(ctxt)
-	if top {
-		if s.Attr.StackCheck() {
-			return 0
-		}
-		s.Attr |= sym.AttrStackCheck
-	}
-
-	if depth > 500 {
-		Errorf(s, "nosplit stack check too deep")
-		stkbroke(ctxt, up, 0)
-		return -1
-	}
-
-	if s.Attr.External() || s.FuncInfo == nil {
-		// external function.
-		// should never be called directly.
-		// onlyctxt.Diagnose the direct caller.
-		// TODO(mwhudson): actually think about this.
-		// TODO(khr): disabled for now. Calls to external functions can only happen on the g0 stack.
-		// See the trampolines in src/runtime/sys_darwin_$ARCH.go.
-		if depth == 1 && s.Type != sym.SXREF && !ctxt.DynlinkingGo() &&
-			ctxt.BuildMode != BuildModeCArchive && ctxt.BuildMode != BuildModePIE && ctxt.BuildMode != BuildModeCShared && ctxt.BuildMode != BuildModePlugin {
-			//Errorf(s, "call to external function")
-		}
-		return -1
-	}
-
-	if limit < 0 {
-		stkbroke(ctxt, up, limit)
-		return -1
-	}
-
-	// morestack looks like it calls functions,
-	// but it switches the stack pointer first.
-	if s == morestack {
-		return 0
-	}
-
-	var ch chain
-	ch.up = up
-
-	if !s.Attr.NoSplit() {
-		// Ensure we have enough stack to call morestack.
-		ch.limit = limit - callsize(ctxt)
-		ch.sym = morestack
-		if stkcheck(ctxt, &ch, depth+1) < 0 {
-			return -1
-		}
-		if !top {
-			return 0
-		}
-		// Raise limit to allow frame.
-		locals := int32(0)
-		if s.FuncInfo != nil {
-			locals = s.FuncInfo.Locals
-		}
-		limit = objabi.StackLimit + int(locals) + int(ctxt.FixedFrameSize())
-	}
-
-	// Walk through sp adjustments in function, consuming relocs.
-	ri := 0
-
-	endr := len(s.R)
-	var ch1 chain
-	pcsp := obj.NewPCIter(uint32(ctxt.Arch.MinLC))
-	var r *sym.Reloc
-	for pcsp.Init(s.FuncInfo.Pcsp.P); !pcsp.Done; pcsp.Next() {
-		// pcsp.value is in effect for [pcsp.pc, pcsp.nextpc).
-
-		// Check stack size in effect for this span.
-		if int32(limit)-pcsp.Value < 0 {
-			stkbroke(ctxt, up, int(int32(limit)-pcsp.Value))
-			return -1
-		}
-
-		// Process calls in this span.
-		for ; ri < endr && uint32(s.R[ri].Off) < pcsp.NextPC; ri++ {
-			r = &s.R[ri]
-			switch {
-			case r.Type.IsDirectCall():
-				ch.limit = int(int32(limit) - pcsp.Value - int32(callsize(ctxt)))
-				ch.sym = r.Sym
-				if stkcheck(ctxt, &ch, depth+1) < 0 {
-					return -1
-				}
-
-			// Indirect call. Assume it is a call to a splitting function,
-			// so we have to make sure it can call morestack.
-			// Arrange the data structures to report both calls, so that
-			// if there is an error, stkprint shows all the steps involved.
-			case r.Type == objabi.R_CALLIND:
-				ch.limit = int(int32(limit) - pcsp.Value - int32(callsize(ctxt)))
-				ch.sym = nil
-				ch1.limit = ch.limit - callsize(ctxt) // for morestack in called prologue
-				ch1.up = &ch
-				ch1.sym = morestack
-				if stkcheck(ctxt, &ch1, depth+2) < 0 {
-					return -1
-				}
-			}
-		}
-	}
-
-	return 0
-}
-
-func stkbroke(ctxt *Link, ch *chain, limit int) {
-	Errorf(ch.sym, "nosplit stack overflow")
-	stkprint(ctxt, ch, limit)
-}
-
-func stkprint(ctxt *Link, ch *chain, limit int) {
-	var name string
-
-	if ch.sym != nil {
-		name = ch.sym.Name
-		if ch.sym.Attr.NoSplit() {
-			name += " (nosplit)"
-		}
-	} else {
-		name = "function pointer"
-	}
-
-	if ch.up == nil {
-		// top of chain.  ch->sym != nil.
-		if ch.sym.Attr.NoSplit() {
-			fmt.Printf("\t%d\tassumed on entry to %s\n", ch.limit, name)
-		} else {
-			fmt.Printf("\t%d\tguaranteed after split check in %s\n", ch.limit, name)
-		}
-	} else {
-		stkprint(ctxt, ch.up, ch.limit+callsize(ctxt))
-		if !haslinkregister(ctxt) {
-			fmt.Printf("\t%d\ton entry to %s\n", ch.limit, name)
-		}
-	}
-
-	if ch.limit != limit {
-		fmt.Printf("\t%d\tafter %s uses %d\n", limit, name, ch.limit-limit)
-	}
-}
-
-func usage() {
-	fmt.Fprintf(os.Stderr, "usage: link [options] main.o\n")
-	objabi.Flagprint(os.Stderr)
-	Exit(2)
-}
-
-type SymbolType int8
-
-const (
-	// see also https://9p.io/magic/man2html/1/nm
-	TextSym      SymbolType = 'T'
-	DataSym      SymbolType = 'D'
-	BSSSym       SymbolType = 'B'
-	UndefinedSym SymbolType = 'U'
-	TLSSym       SymbolType = 't'
-	FrameSym     SymbolType = 'm'
-	ParamSym     SymbolType = 'p'
-	AutoSym      SymbolType = 'a'
-
-	// Deleted auto (not a real sym, just placeholder for type)
-	DeletedAutoSym = 'x'
-)
-
-func genasmsym(ctxt *Link, put func(*Link, *sym.Symbol, string, SymbolType, int64, *sym.Symbol)) {
-	// These symbols won't show up in the first loop below because we
-	// skip sym.STEXT symbols. Normal sym.STEXT symbols are emitted by walking textp.
-	s := ctxt.Syms.Lookup("runtime.text", 0)
-	if s.Type == sym.STEXT {
-		// We've already included this symbol in ctxt.Textp
-		// if ctxt.DynlinkingGo() && ctxt.HeadType == objabi.Hdarwin or
-		// on AIX with external linker.
-		// See data.go:/textaddress
-		if !(ctxt.DynlinkingGo() && ctxt.HeadType == objabi.Hdarwin) && !(ctxt.HeadType == objabi.Haix && ctxt.LinkMode == LinkExternal) {
-			put(ctxt, s, s.Name, TextSym, s.Value, nil)
-		}
-	}
-
-	n := 0
-
-	// Generate base addresses for all text sections if there are multiple
-	for _, sect := range Segtext.Sections {
-		if n == 0 {
-			n++
-			continue
-		}
-		if sect.Name != ".text" || (ctxt.HeadType == objabi.Haix && ctxt.LinkMode == LinkExternal) {
-			// On AIX, runtime.text.X are symbols already in the symtab.
-			break
-		}
-		s = ctxt.Syms.ROLookup(fmt.Sprintf("runtime.text.%d", n), 0)
-		if s == nil {
-			break
-		}
-		if s.Type == sym.STEXT {
-			put(ctxt, s, s.Name, TextSym, s.Value, nil)
-		}
-		n++
-	}
-
-	s = ctxt.Syms.Lookup("runtime.etext", 0)
-	if s.Type == sym.STEXT {
-		// We've already included this symbol in ctxt.Textp
-		// if ctxt.DynlinkingGo() && ctxt.HeadType == objabi.Hdarwin or
-		// on AIX with external linker.
-		// See data.go:/textaddress
-		if !(ctxt.DynlinkingGo() && ctxt.HeadType == objabi.Hdarwin) && !(ctxt.HeadType == objabi.Haix && ctxt.LinkMode == LinkExternal) {
-			put(ctxt, s, s.Name, TextSym, s.Value, nil)
-		}
-	}
-
-	shouldBeInSymbolTable := func(s *sym.Symbol) bool {
-		if s.Attr.NotInSymbolTable() {
-			return false
-		}
-		if ctxt.HeadType == objabi.Haix && s.Name == ".go.buildinfo" {
-			// On AIX, .go.buildinfo must be in the symbol table as
-			// it has relocations.
-			return true
-		}
-		if (s.Name == "" || s.Name[0] == '.') && !s.IsFileLocal() && s.Name != ".rathole" && s.Name != ".TOC." {
-			return false
-		}
-		return true
-	}
-
-	for _, s := range ctxt.Syms.Allsym {
-		if !shouldBeInSymbolTable(s) {
-			continue
-		}
-		switch s.Type {
-		case sym.SCONST,
-			sym.SRODATA,
-			sym.SSYMTAB,
-			sym.SPCLNTAB,
-			sym.SINITARR,
-			sym.SDATA,
-			sym.SNOPTRDATA,
-			sym.SELFROSECT,
-			sym.SMACHOGOT,
-			sym.STYPE,
-			sym.SSTRING,
-			sym.SGOSTRING,
-			sym.SGOFUNC,
-			sym.SGCBITS,
-			sym.STYPERELRO,
-			sym.SSTRINGRELRO,
-			sym.SGOSTRINGRELRO,
-			sym.SGOFUNCRELRO,
-			sym.SGCBITSRELRO,
-			sym.SRODATARELRO,
-			sym.STYPELINK,
-			sym.SITABLINK,
-			sym.SWINDOWS:
-			if !s.Attr.Reachable() {
-				continue
-			}
-			put(ctxt, s, s.Name, DataSym, Symaddr(s), s.Gotype)
-
-		case sym.SBSS, sym.SNOPTRBSS, sym.SLIBFUZZER_EXTRA_COUNTER:
-			if !s.Attr.Reachable() {
-				continue
-			}
-			if len(s.P) > 0 {
-				Errorf(s, "should not be bss (size=%d type=%v special=%v)", len(s.P), s.Type, s.Attr.Special())
-			}
-			put(ctxt, s, s.Name, BSSSym, Symaddr(s), s.Gotype)
-
-		case sym.SUNDEFEXT:
-			if ctxt.HeadType == objabi.Hwindows || ctxt.HeadType == objabi.Haix || ctxt.IsELF {
-				put(ctxt, s, s.Name, UndefinedSym, s.Value, nil)
-			}
-
-		case sym.SHOSTOBJ:
-			if !s.Attr.Reachable() {
-				continue
-			}
-			if ctxt.HeadType == objabi.Hwindows || ctxt.IsELF {
-				put(ctxt, s, s.Name, UndefinedSym, s.Value, nil)
-			}
-
-		case sym.SDYNIMPORT:
-			if !s.Attr.Reachable() {
-				continue
-			}
-			put(ctxt, s, s.Extname(), UndefinedSym, 0, nil)
-
-		case sym.STLSBSS:
-			if ctxt.LinkMode == LinkExternal {
-				put(ctxt, s, s.Name, TLSSym, Symaddr(s), s.Gotype)
-			}
-		}
-	}
-
-	for _, s := range ctxt.Textp {
-		put(ctxt, s, s.Name, TextSym, s.Value, s.Gotype)
-
-		locals := int32(0)
-		if s.FuncInfo != nil {
-			locals = s.FuncInfo.Locals
-		}
-		// NOTE(ality): acid can't produce a stack trace without .frame symbols
-		put(ctxt, nil, ".frame", FrameSym, int64(locals)+int64(ctxt.Arch.PtrSize), nil)
-
-		if s.FuncInfo == nil {
-			continue
-		}
-	}
-
-	if ctxt.Debugvlog != 0 || *flagN {
-		ctxt.Logf("symsize = %d\n", uint32(Symsize))
-	}
-}
-
-func Symaddr(s *sym.Symbol) int64 {
-	if !s.Attr.Reachable() {
-		Errorf(s, "unreachable symbol in symaddr")
-	}
-	return s.Value
-}
-
-func (ctxt *Link) xdefine(p string, t sym.SymKind, v int64) {
-	s := ctxt.Syms.Lookup(p, 0)
-	s.Type = t
-	s.Value = v
-	s.Attr |= sym.AttrReachable
-	s.Attr |= sym.AttrSpecial
-	s.Attr |= sym.AttrLocal
-}
-
-func datoff(s *sym.Symbol, addr int64) int64 {
-	if uint64(addr) >= Segdata.Vaddr {
-		return int64(uint64(addr) - Segdata.Vaddr + Segdata.Fileoff)
-	}
-	if uint64(addr) >= Segtext.Vaddr {
-		return int64(uint64(addr) - Segtext.Vaddr + Segtext.Fileoff)
-	}
-	Errorf(s, "invalid datoff %#x", addr)
-	return 0
-}
-
-func Entryvalue(ctxt *Link) int64 {
-	a := *flagEntrySymbol
-	if a[0] >= '0' && a[0] <= '9' {
-		return atolwhex(a)
-	}
-	s := ctxt.Syms.Lookup(a, 0)
-	if s.Type == 0 {
-		return *FlagTextAddr
-	}
-	if ctxt.HeadType != objabi.Haix && s.Type != sym.STEXT {
-		Errorf(s, "entry not text")
-	}
-	return s.Value
-}
-
-func undefsym(ctxt *Link, s *sym.Symbol) {
-	var r *sym.Reloc
-
-	for i := 0; i < len(s.R); i++ {
-		r = &s.R[i]
-		if r.Sym == nil { // happens for some external ARM relocs
-			continue
-		}
-		// TODO(mwhudson): the test of VisibilityHidden here probably doesn't make
-		// sense and should be removed when someone has thought about it properly.
-		if (r.Sym.Type == sym.Sxxx || r.Sym.Type == sym.SXREF) && !r.Sym.Attr.VisibilityHidden() {
-			Errorf(s, "undefined: %q", r.Sym.Name)
-		}
-		if !r.Sym.Attr.Reachable() && r.Type != objabi.R_WEAKADDROFF {
-			Errorf(s, "relocation target %q", r.Sym.Name)
-		}
-	}
-}
-
-func (ctxt *Link) undef() {
-	// undefsym performs checks (almost) identical to checks
-	// that report undefined relocations in relocsym.
-	// Both undefsym and relocsym can report same symbol as undefined,
-	// which results in error message duplication (see #10978).
-	//
-	// The undef is run after Arch.Asmb and could detect some
-	// programming errors there, but if object being linked is already
-	// failed with errors, it is better to avoid duplicated errors.
-	if nerrors > 0 {
-		return
-	}
-
-	for _, s := range ctxt.Textp {
-		undefsym(ctxt, s)
-	}
-	for _, s := range datap {
-		undefsym(ctxt, s)
-	}
-	if nerrors > 0 {
-		errorexit()
-	}
-}
-
-func (ctxt *Link) callgraph() {
-	if !*FlagC {
-		return
-	}
-
-	var i int
-	var r *sym.Reloc
-	for _, s := range ctxt.Textp {
-		for i = 0; i < len(s.R); i++ {
-			r = &s.R[i]
-			if r.Sym == nil {
-				continue
-			}
-			if r.Type.IsDirectCall() && r.Sym.Type == sym.STEXT {
-				ctxt.Logf("%s calls %s\n", s.Name, r.Sym.Name)
-			}
-		}
-	}
-}
-
-func Rnd(v int64, r int64) int64 {
-	if r <= 0 {
-		return v
-	}
-	v += r - 1
-	c := v % r
-	if c < 0 {
-		c += r
-	}
-	v -= c
-	return v
-}
-
-func bgetc(r *bio.Reader) int {
-	c, err := r.ReadByte()
-	if err != nil {
-		if err != io.EOF {
-			log.Fatalf("reading input: %v", err)
-		}
-		return -1
-	}
-	return int(c)
-}
-
-type markKind uint8 // for postorder traversal
-const (
-	_ markKind = iota
-	visiting
-	visited
-)
-
-func postorder(libs []*sym.Library) []*sym.Library {
-	order := make([]*sym.Library, 0, len(libs)) // hold the result
-	mark := make(map[*sym.Library]markKind, len(libs))
-	for _, lib := range libs {
-		dfs(lib, mark, &order)
-	}
-	return order
-}
-
-func dfs(lib *sym.Library, mark map[*sym.Library]markKind, order *[]*sym.Library) {
-	if mark[lib] == visited {
-		return
-	}
-	if mark[lib] == visiting {
-		panic("found import cycle while visiting " + lib.Pkg)
-	}
-	mark[lib] = visiting
-	for _, i := range lib.Imports {
-		dfs(i, mark, order)
-	}
-	mark[lib] = visited
-	*order = append(*order, lib)
-}
-
-func (ctxt *Link) loadlibfull() {
-	// Load full symbol contents, resolve indexed references.
-	ctxt.loader.LoadFull(ctxt.Arch, ctxt.Syms)
-
-	// Pull the symbols out.
-	ctxt.loader.ExtractSymbols(ctxt.Syms)
-
-	// Load cgo directives.
-	for _, d := range ctxt.cgodata {
-		setCgoAttr(ctxt, ctxt.Syms.Lookup, d.file, d.pkg, d.directives)
-	}
-
-	setupdynexp(ctxt)
-
-	// Populate ctxt.Reachparent if appropriate.
-	if ctxt.Reachparent != nil {
-		for i := 0; i < len(ctxt.loader.Reachparent); i++ {
-			p := ctxt.loader.Reachparent[i]
-			if p == 0 {
-				continue
-			}
-			if p == loader.Sym(i) {
-				panic("self-cycle in reachparent")
-			}
-			sym := ctxt.loader.Syms[i]
-			psym := ctxt.loader.Syms[p]
-			ctxt.Reachparent[sym] = psym
-		}
-	}
-
-	// Drop the reference.
-	ctxt.loader = nil
-	ctxt.cgodata = nil
-
-	addToTextp(ctxt)
-}
-
-func (ctxt *Link) dumpsyms() {
-	for _, s := range ctxt.Syms.Allsym {
-		fmt.Printf("%s %s %p %v %v\n", s, s.Type, s, s.Attr.Reachable(), s.Attr.OnList())
-		for i := range s.R {
-			fmt.Println("\t", s.R[i].Type, s.R[i].Sym)
-		}
-	}
-}
diff --git a/src/cmd/oldlink/internal/ld/link.go b/src/cmd/oldlink/internal/ld/link.go
deleted file mode 100644
index 514abee..0000000
--- a/src/cmd/oldlink/internal/ld/link.go
+++ /dev/null
@@ -1,187 +0,0 @@
-// Derived from Inferno utils/6l/l.h and related files.
-// https://bitbucket.org/inferno-os/inferno-os/src/master/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
-
-import (
-	"bufio"
-	"cmd/internal/obj"
-	"cmd/internal/objabi"
-	"cmd/internal/sys"
-	"cmd/oldlink/internal/loader"
-	"cmd/oldlink/internal/sym"
-	"debug/elf"
-	"fmt"
-)
-
-type Shlib struct {
-	Path            string
-	Hash            []byte
-	Deps            []string
-	File            *elf.File
-	gcdataAddresses map[*sym.Symbol]uint64
-}
-
-// Link holds the context for writing object code from a compiler
-// or for reading that input into the linker.
-type Link struct {
-	Out *OutBuf
-
-	Syms *sym.Symbols
-
-	Arch      *sys.Arch
-	Debugvlog int
-	Bso       *bufio.Writer
-
-	Loaded bool // set after all inputs have been loaded as symbols
-
-	IsELF    bool
-	HeadType objabi.HeadType
-
-	linkShared    bool // link against installed Go shared libraries
-	LinkMode      LinkMode
-	BuildMode     BuildMode
-	canUsePlugins bool // initialized when Loaded is set to true
-	compressDWARF bool
-
-	Tlsg         *sym.Symbol
-	Libdir       []string
-	Library      []*sym.Library
-	LibraryByPkg map[string]*sym.Library
-	Shlibs       []Shlib
-	Tlsoffset    int
-	Textp        []*sym.Symbol
-	Filesyms     []*sym.Symbol
-	Moduledata   *sym.Symbol
-
-	PackageFile  map[string]string
-	PackageShlib map[string]string
-
-	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
-
-	compUnits []*sym.CompilationUnit // DWARF compilation units
-	runtimeCU *sym.CompilationUnit   // One of the runtime CUs, the last one seen.
-
-	relocbuf []byte // temporary buffer for applying relocations
-
-	loader  *loader.Loader
-	cgodata []cgodata // cgo directives to load, three strings are args for loadcgo
-
-	cgo_export_static  map[string]bool
-	cgo_export_dynamic map[string]bool
-}
-
-type cgodata struct {
-	file       string
-	pkg        string
-	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 && rs.Type != sym.SXREF {
-					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
-// the hardware stack pointer and the local variable area.
-func (ctxt *Link) FixedFrameSize() int64 {
-	switch ctxt.Arch.Family {
-	case sys.AMD64, sys.I386:
-		return 0
-	case sys.PPC64:
-		// PIC code on ppc64le requires 32 bytes of stack, and it's easier to
-		// just use that much stack always on ppc64x.
-		return int64(4 * ctxt.Arch.PtrSize)
-	default:
-		return int64(ctxt.Arch.PtrSize)
-	}
-}
-
-func (ctxt *Link) Logf(format string, args ...interface{}) {
-	fmt.Fprintf(ctxt.Bso, format, args...)
-	ctxt.Bso.Flush()
-}
-
-func addImports(ctxt *Link, l *sym.Library, pn string) {
-	pkg := objabi.PathToPrefix(l.Pkg)
-	for _, importStr := range l.ImportStrings {
-		lib := addlib(ctxt, pkg, pn, importStr)
-		if lib != nil {
-			l.Imports = append(l.Imports, lib)
-		}
-	}
-	l.ImportStrings = nil
-}
diff --git a/src/cmd/oldlink/internal/ld/macho.go b/src/cmd/oldlink/internal/ld/macho.go
deleted file mode 100644
index 960ed29..0000000
--- a/src/cmd/oldlink/internal/ld/macho.go
+++ /dev/null
@@ -1,1119 +0,0 @@
-// Copyright 2009 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 (
-	"bytes"
-	"cmd/internal/objabi"
-	"cmd/internal/sys"
-	"cmd/oldlink/internal/sym"
-	"debug/macho"
-	"encoding/binary"
-	"fmt"
-	"io"
-	"os"
-	"sort"
-	"strings"
-)
-
-type MachoHdr struct {
-	cpu    uint32
-	subcpu uint32
-}
-
-type MachoSect struct {
-	name    string
-	segname string
-	addr    uint64
-	size    uint64
-	off     uint32
-	align   uint32
-	reloc   uint32
-	nreloc  uint32
-	flag    uint32
-	res1    uint32
-	res2    uint32
-}
-
-type MachoSeg struct {
-	name       string
-	vsize      uint64
-	vaddr      uint64
-	fileoffset uint64
-	filesize   uint64
-	prot1      uint32
-	prot2      uint32
-	nsect      uint32
-	msect      uint32
-	sect       []MachoSect
-	flag       uint32
-}
-
-// MachoPlatformLoad represents a LC_VERSION_MIN_* or
-// LC_BUILD_VERSION load command.
-type MachoPlatformLoad struct {
-	platform MachoPlatform // One of PLATFORM_* constants.
-	cmd      MachoLoad
-}
-
-type MachoLoad struct {
-	type_ uint32
-	data  []uint32
-}
-
-type MachoPlatform int
-
-/*
- * Total amount of space to reserve at the start of the file
- * for Header, PHeaders, and SHeaders.
- * May waste some.
- */
-const (
-	INITIAL_MACHO_HEADR = 4 * 1024
-)
-
-const (
-	MACHO_CPU_AMD64               = 1<<24 | 7
-	MACHO_CPU_386                 = 7
-	MACHO_SUBCPU_X86              = 3
-	MACHO_CPU_ARM                 = 12
-	MACHO_SUBCPU_ARM              = 0
-	MACHO_SUBCPU_ARMV7            = 9
-	MACHO_CPU_ARM64               = 1<<24 | 12
-	MACHO_SUBCPU_ARM64_ALL        = 0
-	MACHO32SYMSIZE                = 12
-	MACHO64SYMSIZE                = 16
-	MACHO_X86_64_RELOC_UNSIGNED   = 0
-	MACHO_X86_64_RELOC_SIGNED     = 1
-	MACHO_X86_64_RELOC_BRANCH     = 2
-	MACHO_X86_64_RELOC_GOT_LOAD   = 3
-	MACHO_X86_64_RELOC_GOT        = 4
-	MACHO_X86_64_RELOC_SUBTRACTOR = 5
-	MACHO_X86_64_RELOC_SIGNED_1   = 6
-	MACHO_X86_64_RELOC_SIGNED_2   = 7
-	MACHO_X86_64_RELOC_SIGNED_4   = 8
-	MACHO_ARM_RELOC_VANILLA       = 0
-	MACHO_ARM_RELOC_PAIR          = 1
-	MACHO_ARM_RELOC_SECTDIFF      = 2
-	MACHO_ARM_RELOC_BR24          = 5
-	MACHO_ARM64_RELOC_UNSIGNED    = 0
-	MACHO_ARM64_RELOC_BRANCH26    = 2
-	MACHO_ARM64_RELOC_PAGE21      = 3
-	MACHO_ARM64_RELOC_PAGEOFF12   = 4
-	MACHO_ARM64_RELOC_ADDEND      = 10
-	MACHO_GENERIC_RELOC_VANILLA   = 0
-	MACHO_FAKE_GOTPCREL           = 100
-)
-
-const (
-	MH_MAGIC    = 0xfeedface
-	MH_MAGIC_64 = 0xfeedfacf
-
-	MH_OBJECT  = 0x1
-	MH_EXECUTE = 0x2
-
-	MH_NOUNDEFS = 0x1
-)
-
-const (
-	LC_SEGMENT                  = 0x1
-	LC_SYMTAB                   = 0x2
-	LC_SYMSEG                   = 0x3
-	LC_THREAD                   = 0x4
-	LC_UNIXTHREAD               = 0x5
-	LC_LOADFVMLIB               = 0x6
-	LC_IDFVMLIB                 = 0x7
-	LC_IDENT                    = 0x8
-	LC_FVMFILE                  = 0x9
-	LC_PREPAGE                  = 0xa
-	LC_DYSYMTAB                 = 0xb
-	LC_LOAD_DYLIB               = 0xc
-	LC_ID_DYLIB                 = 0xd
-	LC_LOAD_DYLINKER            = 0xe
-	LC_ID_DYLINKER              = 0xf
-	LC_PREBOUND_DYLIB           = 0x10
-	LC_ROUTINES                 = 0x11
-	LC_SUB_FRAMEWORK            = 0x12
-	LC_SUB_UMBRELLA             = 0x13
-	LC_SUB_CLIENT               = 0x14
-	LC_SUB_LIBRARY              = 0x15
-	LC_TWOLEVEL_HINTS           = 0x16
-	LC_PREBIND_CKSUM            = 0x17
-	LC_LOAD_WEAK_DYLIB          = 0x80000018
-	LC_SEGMENT_64               = 0x19
-	LC_ROUTINES_64              = 0x1a
-	LC_UUID                     = 0x1b
-	LC_RPATH                    = 0x8000001c
-	LC_CODE_SIGNATURE           = 0x1d
-	LC_SEGMENT_SPLIT_INFO       = 0x1e
-	LC_REEXPORT_DYLIB           = 0x8000001f
-	LC_LAZY_LOAD_DYLIB          = 0x20
-	LC_ENCRYPTION_INFO          = 0x21
-	LC_DYLD_INFO                = 0x22
-	LC_DYLD_INFO_ONLY           = 0x80000022
-	LC_LOAD_UPWARD_DYLIB        = 0x80000023
-	LC_VERSION_MIN_MACOSX       = 0x24
-	LC_VERSION_MIN_IPHONEOS     = 0x25
-	LC_FUNCTION_STARTS          = 0x26
-	LC_DYLD_ENVIRONMENT         = 0x27
-	LC_MAIN                     = 0x80000028
-	LC_DATA_IN_CODE             = 0x29
-	LC_SOURCE_VERSION           = 0x2A
-	LC_DYLIB_CODE_SIGN_DRS      = 0x2B
-	LC_ENCRYPTION_INFO_64       = 0x2C
-	LC_LINKER_OPTION            = 0x2D
-	LC_LINKER_OPTIMIZATION_HINT = 0x2E
-	LC_VERSION_MIN_TVOS         = 0x2F
-	LC_VERSION_MIN_WATCHOS      = 0x30
-	LC_VERSION_NOTE             = 0x31
-	LC_BUILD_VERSION            = 0x32
-)
-
-const (
-	S_REGULAR                  = 0x0
-	S_ZEROFILL                 = 0x1
-	S_NON_LAZY_SYMBOL_POINTERS = 0x6
-	S_SYMBOL_STUBS             = 0x8
-	S_MOD_INIT_FUNC_POINTERS   = 0x9
-	S_ATTR_PURE_INSTRUCTIONS   = 0x80000000
-	S_ATTR_DEBUG               = 0x02000000
-	S_ATTR_SOME_INSTRUCTIONS   = 0x00000400
-)
-
-const (
-	PLATFORM_MACOS    MachoPlatform = 1
-	PLATFORM_IOS      MachoPlatform = 2
-	PLATFORM_TVOS     MachoPlatform = 3
-	PLATFORM_WATCHOS  MachoPlatform = 4
-	PLATFORM_BRIDGEOS MachoPlatform = 5
-)
-
-// Mach-O file writing
-// https://developer.apple.com/mac/library/DOCUMENTATION/DeveloperTools/Conceptual/MachORuntime/Reference/reference.html
-
-var machohdr MachoHdr
-
-var load []MachoLoad
-
-var machoPlatform MachoPlatform
-
-var seg [16]MachoSeg
-
-var nseg int
-
-var ndebug int
-
-var nsect int
-
-const (
-	SymKindLocal = 0 + iota
-	SymKindExtdef
-	SymKindUndef
-	NumSymKind
-)
-
-var nkind [NumSymKind]int
-
-var sortsym []*sym.Symbol
-
-var nsortsym int
-
-// Amount of space left for adding load commands
-// that refer to dynamic libraries. Because these have
-// to go in the Mach-O header, we can't just pick a
-// "big enough" header size. The initial header is
-// one page, the non-dynamic library stuff takes
-// up about 1300 bytes; we overestimate that as 2k.
-var loadBudget = INITIAL_MACHO_HEADR - 2*1024
-
-func getMachoHdr() *MachoHdr {
-	return &machohdr
-}
-
-func newMachoLoad(arch *sys.Arch, type_ uint32, ndata uint32) *MachoLoad {
-	if arch.PtrSize == 8 && (ndata&1 != 0) {
-		ndata++
-	}
-
-	load = append(load, MachoLoad{})
-	l := &load[len(load)-1]
-	l.type_ = type_
-	l.data = make([]uint32, ndata)
-	return l
-}
-
-func newMachoSeg(name string, msect int) *MachoSeg {
-	if nseg >= len(seg) {
-		Exitf("too many segs")
-	}
-
-	s := &seg[nseg]
-	nseg++
-	s.name = name
-	s.msect = uint32(msect)
-	s.sect = make([]MachoSect, msect)
-	return s
-}
-
-func newMachoSect(seg *MachoSeg, name string, segname string) *MachoSect {
-	if seg.nsect >= seg.msect {
-		Exitf("too many sects in segment %s", seg.name)
-	}
-
-	s := &seg.sect[seg.nsect]
-	seg.nsect++
-	s.name = name
-	s.segname = segname
-	nsect++
-	return s
-}
-
-// Generic linking code.
-
-var dylib []string
-
-var linkoff int64
-
-func machowrite(arch *sys.Arch, out *OutBuf, linkmode LinkMode) int {
-	o1 := out.Offset()
-
-	loadsize := 4 * 4 * ndebug
-	for i := range load {
-		loadsize += 4 * (len(load[i].data) + 2)
-	}
-	if arch.PtrSize == 8 {
-		loadsize += 18 * 4 * nseg
-		loadsize += 20 * 4 * nsect
-	} else {
-		loadsize += 14 * 4 * nseg
-		loadsize += 17 * 4 * nsect
-	}
-
-	if arch.PtrSize == 8 {
-		out.Write32(MH_MAGIC_64)
-	} else {
-		out.Write32(MH_MAGIC)
-	}
-	out.Write32(machohdr.cpu)
-	out.Write32(machohdr.subcpu)
-	if linkmode == LinkExternal {
-		out.Write32(MH_OBJECT) /* file type - mach object */
-	} else {
-		out.Write32(MH_EXECUTE) /* file type - mach executable */
-	}
-	out.Write32(uint32(len(load)) + uint32(nseg) + uint32(ndebug))
-	out.Write32(uint32(loadsize))
-	if nkind[SymKindUndef] == 0 {
-		out.Write32(MH_NOUNDEFS) /* flags - no undefines */
-	} else {
-		out.Write32(0) /* flags */
-	}
-	if arch.PtrSize == 8 {
-		out.Write32(0) /* reserved */
-	}
-
-	for i := 0; i < nseg; i++ {
-		s := &seg[i]
-		if arch.PtrSize == 8 {
-			out.Write32(LC_SEGMENT_64)
-			out.Write32(72 + 80*s.nsect)
-			out.WriteStringN(s.name, 16)
-			out.Write64(s.vaddr)
-			out.Write64(s.vsize)
-			out.Write64(s.fileoffset)
-			out.Write64(s.filesize)
-			out.Write32(s.prot1)
-			out.Write32(s.prot2)
-			out.Write32(s.nsect)
-			out.Write32(s.flag)
-		} else {
-			out.Write32(LC_SEGMENT)
-			out.Write32(56 + 68*s.nsect)
-			out.WriteStringN(s.name, 16)
-			out.Write32(uint32(s.vaddr))
-			out.Write32(uint32(s.vsize))
-			out.Write32(uint32(s.fileoffset))
-			out.Write32(uint32(s.filesize))
-			out.Write32(s.prot1)
-			out.Write32(s.prot2)
-			out.Write32(s.nsect)
-			out.Write32(s.flag)
-		}
-
-		for j := uint32(0); j < s.nsect; j++ {
-			t := &s.sect[j]
-			if arch.PtrSize == 8 {
-				out.WriteStringN(t.name, 16)
-				out.WriteStringN(t.segname, 16)
-				out.Write64(t.addr)
-				out.Write64(t.size)
-				out.Write32(t.off)
-				out.Write32(t.align)
-				out.Write32(t.reloc)
-				out.Write32(t.nreloc)
-				out.Write32(t.flag)
-				out.Write32(t.res1) /* reserved */
-				out.Write32(t.res2) /* reserved */
-				out.Write32(0)      /* reserved */
-			} else {
-				out.WriteStringN(t.name, 16)
-				out.WriteStringN(t.segname, 16)
-				out.Write32(uint32(t.addr))
-				out.Write32(uint32(t.size))
-				out.Write32(t.off)
-				out.Write32(t.align)
-				out.Write32(t.reloc)
-				out.Write32(t.nreloc)
-				out.Write32(t.flag)
-				out.Write32(t.res1) /* reserved */
-				out.Write32(t.res2) /* reserved */
-			}
-		}
-	}
-
-	for i := range load {
-		l := &load[i]
-		out.Write32(l.type_)
-		out.Write32(4 * (uint32(len(l.data)) + 2))
-		for j := 0; j < len(l.data); j++ {
-			out.Write32(l.data[j])
-		}
-	}
-
-	return int(out.Offset() - o1)
-}
-
-func (ctxt *Link) domacho() {
-	if *FlagD {
-		return
-	}
-
-	// Copy platform load command.
-	for _, h := range hostobj {
-		load, err := hostobjMachoPlatform(&h)
-		if err != nil {
-			Exitf("%v", err)
-		}
-		if load != nil {
-			machoPlatform = load.platform
-			ml := newMachoLoad(ctxt.Arch, load.cmd.type_, uint32(len(load.cmd.data)))
-			copy(ml.data, load.cmd.data)
-			break
-		}
-	}
-	if machoPlatform == 0 {
-		switch ctxt.Arch.Family {
-		default:
-			machoPlatform = PLATFORM_MACOS
-			if ctxt.LinkMode == LinkInternal {
-				// For lldb, must say LC_VERSION_MIN_MACOSX or else
-				// it won't know that this Mach-O binary is from OS X
-				// (could be iOS or WatchOS instead).
-				// Go on iOS uses linkmode=external, and linkmode=external
-				// adds this itself. So we only need this code for linkmode=internal
-				// and we can assume OS X.
-				//
-				// See golang.org/issues/12941.
-				//
-				// The version must be at least 10.9; see golang.org/issues/30488.
-				ml := newMachoLoad(ctxt.Arch, LC_VERSION_MIN_MACOSX, 2)
-				ml.data[0] = 10<<16 | 9<<8 | 0<<0 // OS X version 10.9.0
-				ml.data[1] = 10<<16 | 9<<8 | 0<<0 // SDK 10.9.0
-			}
-		case sys.ARM, sys.ARM64:
-			machoPlatform = PLATFORM_IOS
-		}
-	}
-
-	// empirically, string table must begin with " \x00".
-	s := ctxt.Syms.Lookup(".machosymstr", 0)
-
-	s.Type = sym.SMACHOSYMSTR
-	s.Attr |= sym.AttrReachable
-	s.AddUint8(' ')
-	s.AddUint8('\x00')
-
-	s = ctxt.Syms.Lookup(".machosymtab", 0)
-	s.Type = sym.SMACHOSYMTAB
-	s.Attr |= sym.AttrReachable
-
-	if ctxt.LinkMode != LinkExternal {
-		s := ctxt.Syms.Lookup(".plt", 0) // will be __symbol_stub
-		s.Type = sym.SMACHOPLT
-		s.Attr |= sym.AttrReachable
-
-		s = ctxt.Syms.Lookup(".got", 0) // will be __nl_symbol_ptr
-		s.Type = sym.SMACHOGOT
-		s.Attr |= sym.AttrReachable
-		s.Align = 4
-
-		s = ctxt.Syms.Lookup(".linkedit.plt", 0) // indirect table for .plt
-		s.Type = sym.SMACHOINDIRECTPLT
-		s.Attr |= sym.AttrReachable
-
-		s = ctxt.Syms.Lookup(".linkedit.got", 0) // indirect table for .got
-		s.Type = sym.SMACHOINDIRECTGOT
-		s.Attr |= sym.AttrReachable
-	}
-
-	// Add a dummy symbol that will become the __asm marker section.
-	if ctxt.LinkMode == LinkExternal {
-		s := ctxt.Syms.Lookup(".llvmasm", 0)
-		s.Type = sym.SMACHO
-		s.Attr |= sym.AttrReachable
-		s.AddUint8(0)
-	}
-}
-
-func machoadddynlib(lib string, linkmode LinkMode) {
-	if seenlib[lib] || linkmode == LinkExternal {
-		return
-	}
-	seenlib[lib] = true
-
-	// Will need to store the library name rounded up
-	// and 24 bytes of header metadata. If not enough
-	// space, grab another page of initial space at the
-	// beginning of the output file.
-	loadBudget -= (len(lib)+7)/8*8 + 24
-
-	if loadBudget < 0 {
-		HEADR += 4096
-		*FlagTextAddr += 4096
-		loadBudget += 4096
-	}
-
-	dylib = append(dylib, lib)
-}
-
-func machoshbits(ctxt *Link, mseg *MachoSeg, sect *sym.Section, segname string) {
-	buf := "__" + strings.Replace(sect.Name[1:], ".", "_", -1)
-
-	var msect *MachoSect
-	if sect.Rwx&1 == 0 && segname != "__DWARF" && (ctxt.Arch.Family == sys.ARM64 ||
-		ctxt.Arch.Family == sys.ARM ||
-		(ctxt.Arch.Family == sys.AMD64 && ctxt.BuildMode != BuildModeExe)) {
-		// Darwin external linker on arm and arm64, and on amd64 in c-shared/c-archive buildmode
-		// complains about absolute relocs in __TEXT, so if the section is not
-		// executable, put it in __DATA segment.
-		msect = newMachoSect(mseg, buf, "__DATA")
-	} else {
-		msect = newMachoSect(mseg, buf, segname)
-	}
-
-	if sect.Rellen > 0 {
-		msect.reloc = uint32(sect.Reloff)
-		msect.nreloc = uint32(sect.Rellen / 8)
-	}
-
-	for 1<<msect.align < sect.Align {
-		msect.align++
-	}
-	msect.addr = sect.Vaddr
-	msect.size = sect.Length
-
-	if sect.Vaddr < sect.Seg.Vaddr+sect.Seg.Filelen {
-		// data in file
-		if sect.Length > sect.Seg.Vaddr+sect.Seg.Filelen-sect.Vaddr {
-			Errorf(nil, "macho cannot represent section %s crossing data and bss", sect.Name)
-		}
-		msect.off = uint32(sect.Seg.Fileoff + sect.Vaddr - sect.Seg.Vaddr)
-	} else {
-		msect.off = 0
-		msect.flag |= S_ZEROFILL
-	}
-
-	if sect.Rwx&1 != 0 {
-		msect.flag |= S_ATTR_SOME_INSTRUCTIONS
-	}
-
-	if sect.Name == ".text" {
-		msect.flag |= S_ATTR_PURE_INSTRUCTIONS
-	}
-
-	if sect.Name == ".plt" {
-		msect.name = "__symbol_stub1"
-		msect.flag = S_ATTR_PURE_INSTRUCTIONS | S_ATTR_SOME_INSTRUCTIONS | S_SYMBOL_STUBS
-		msect.res1 = 0 //nkind[SymKindLocal];
-		msect.res2 = 6
-	}
-
-	if sect.Name == ".got" {
-		msect.name = "__nl_symbol_ptr"
-		msect.flag = S_NON_LAZY_SYMBOL_POINTERS
-		msect.res1 = uint32(ctxt.Syms.Lookup(".linkedit.plt", 0).Size / 4) /* offset into indirect symbol table */
-	}
-
-	if sect.Name == ".init_array" {
-		msect.name = "__mod_init_func"
-		msect.flag = S_MOD_INIT_FUNC_POINTERS
-	}
-
-	// Some platforms such as watchOS and tvOS require binaries with
-	// bitcode enabled. The Go toolchain can't output bitcode, so use
-	// a marker section in the __LLVM segment, "__asm", to tell the Apple
-	// toolchain that the Go text came from assembler and thus has no
-	// bitcode. This is not true, but Kotlin/Native, Rust and Flutter
-	// are also using this trick.
-	if sect.Name == ".llvmasm" {
-		msect.name = "__asm"
-		msect.segname = "__LLVM"
-	}
-
-	if segname == "__DWARF" {
-		msect.flag |= S_ATTR_DEBUG
-	}
-}
-
-func Asmbmacho(ctxt *Link) {
-	/* apple MACH */
-	va := *FlagTextAddr - int64(HEADR)
-
-	mh := getMachoHdr()
-	switch ctxt.Arch.Family {
-	default:
-		Exitf("unknown macho architecture: %v", ctxt.Arch.Family)
-
-	case sys.ARM:
-		mh.cpu = MACHO_CPU_ARM
-		mh.subcpu = MACHO_SUBCPU_ARMV7
-
-	case sys.AMD64:
-		mh.cpu = MACHO_CPU_AMD64
-		mh.subcpu = MACHO_SUBCPU_X86
-
-	case sys.ARM64:
-		mh.cpu = MACHO_CPU_ARM64
-		mh.subcpu = MACHO_SUBCPU_ARM64_ALL
-
-	case sys.I386:
-		mh.cpu = MACHO_CPU_386
-		mh.subcpu = MACHO_SUBCPU_X86
-	}
-
-	var ms *MachoSeg
-	if ctxt.LinkMode == LinkExternal {
-		/* segment for entire file */
-		ms = newMachoSeg("", 40)
-
-		ms.fileoffset = Segtext.Fileoff
-		ms.filesize = Segdwarf.Fileoff + Segdwarf.Filelen - Segtext.Fileoff
-		ms.vsize = Segdwarf.Vaddr + Segdwarf.Length - Segtext.Vaddr
-	}
-
-	/* segment for zero page */
-	if ctxt.LinkMode != LinkExternal {
-		ms = newMachoSeg("__PAGEZERO", 0)
-		ms.vsize = uint64(va)
-	}
-
-	/* text */
-	v := Rnd(int64(uint64(HEADR)+Segtext.Length), int64(*FlagRound))
-
-	if ctxt.LinkMode != LinkExternal {
-		ms = newMachoSeg("__TEXT", 20)
-		ms.vaddr = uint64(va)
-		ms.vsize = uint64(v)
-		ms.fileoffset = 0
-		ms.filesize = uint64(v)
-		ms.prot1 = 7
-		ms.prot2 = 5
-	}
-
-	for _, sect := range Segtext.Sections {
-		machoshbits(ctxt, ms, sect, "__TEXT")
-	}
-
-	/* data */
-	if ctxt.LinkMode != LinkExternal {
-		w := int64(Segdata.Length)
-		ms = newMachoSeg("__DATA", 20)
-		ms.vaddr = uint64(va) + uint64(v)
-		ms.vsize = uint64(w)
-		ms.fileoffset = uint64(v)
-		ms.filesize = Segdata.Filelen
-		ms.prot1 = 3
-		ms.prot2 = 3
-	}
-
-	for _, sect := range Segdata.Sections {
-		machoshbits(ctxt, ms, sect, "__DATA")
-	}
-
-	/* dwarf */
-	if !*FlagW {
-		if ctxt.LinkMode != LinkExternal {
-			ms = newMachoSeg("__DWARF", 20)
-			ms.vaddr = Segdwarf.Vaddr
-			ms.vsize = 0
-			ms.fileoffset = Segdwarf.Fileoff
-			ms.filesize = Segdwarf.Filelen
-		}
-		for _, sect := range Segdwarf.Sections {
-			machoshbits(ctxt, ms, sect, "__DWARF")
-		}
-	}
-
-	if ctxt.LinkMode != LinkExternal {
-		switch ctxt.Arch.Family {
-		default:
-			Exitf("unknown macho architecture: %v", ctxt.Arch.Family)
-
-		case sys.ARM:
-			ml := newMachoLoad(ctxt.Arch, LC_UNIXTHREAD, 17+2)
-			ml.data[0] = 1                           /* thread type */
-			ml.data[1] = 17                          /* word count */
-			ml.data[2+15] = uint32(Entryvalue(ctxt)) /* start pc */
-
-		case sys.AMD64:
-			ml := newMachoLoad(ctxt.Arch, LC_UNIXTHREAD, 42+2)
-			ml.data[0] = 4                           /* thread type */
-			ml.data[1] = 42                          /* word count */
-			ml.data[2+32] = uint32(Entryvalue(ctxt)) /* start pc */
-			ml.data[2+32+1] = uint32(Entryvalue(ctxt) >> 32)
-
-		case sys.ARM64:
-			ml := newMachoLoad(ctxt.Arch, LC_UNIXTHREAD, 68+2)
-			ml.data[0] = 6                           /* thread type */
-			ml.data[1] = 68                          /* word count */
-			ml.data[2+64] = uint32(Entryvalue(ctxt)) /* start pc */
-			ml.data[2+64+1] = uint32(Entryvalue(ctxt) >> 32)
-
-		case sys.I386:
-			ml := newMachoLoad(ctxt.Arch, LC_UNIXTHREAD, 16+2)
-			ml.data[0] = 1                           /* thread type */
-			ml.data[1] = 16                          /* word count */
-			ml.data[2+10] = uint32(Entryvalue(ctxt)) /* start pc */
-		}
-	}
-
-	if !*FlagD {
-		// must match domacholink below
-		s1 := ctxt.Syms.Lookup(".machosymtab", 0)
-		s2 := ctxt.Syms.Lookup(".linkedit.plt", 0)
-		s3 := ctxt.Syms.Lookup(".linkedit.got", 0)
-		s4 := ctxt.Syms.Lookup(".machosymstr", 0)
-
-		if ctxt.LinkMode != LinkExternal {
-			ms := newMachoSeg("__LINKEDIT", 0)
-			ms.vaddr = uint64(va) + uint64(v) + uint64(Rnd(int64(Segdata.Length), int64(*FlagRound)))
-			ms.vsize = uint64(s1.Size) + uint64(s2.Size) + uint64(s3.Size) + uint64(s4.Size)
-			ms.fileoffset = uint64(linkoff)
-			ms.filesize = ms.vsize
-			ms.prot1 = 7
-			ms.prot2 = 3
-		}
-
-		ml := newMachoLoad(ctxt.Arch, LC_SYMTAB, 4)
-		ml.data[0] = uint32(linkoff)                               /* symoff */
-		ml.data[1] = uint32(nsortsym)                              /* nsyms */
-		ml.data[2] = uint32(linkoff + s1.Size + s2.Size + s3.Size) /* stroff */
-		ml.data[3] = uint32(s4.Size)                               /* strsize */
-
-		machodysymtab(ctxt)
-
-		if ctxt.LinkMode != LinkExternal {
-			ml := newMachoLoad(ctxt.Arch, LC_LOAD_DYLINKER, 6)
-			ml.data[0] = 12 /* offset to string */
-			stringtouint32(ml.data[1:], "/usr/lib/dyld")
-
-			for _, lib := range dylib {
-				ml = newMachoLoad(ctxt.Arch, LC_LOAD_DYLIB, 4+(uint32(len(lib))+1+7)/8*2)
-				ml.data[0] = 24 /* offset of string from beginning of load */
-				ml.data[1] = 0  /* time stamp */
-				ml.data[2] = 0  /* version */
-				ml.data[3] = 0  /* compatibility version */
-				stringtouint32(ml.data[4:], lib)
-			}
-		}
-	}
-
-	a := machowrite(ctxt.Arch, ctxt.Out, ctxt.LinkMode)
-	if int32(a) > HEADR {
-		Exitf("HEADR too small: %d > %d", a, HEADR)
-	}
-}
-
-func symkind(s *sym.Symbol) int {
-	if s.Type == sym.SDYNIMPORT {
-		return SymKindUndef
-	}
-	if s.Attr.CgoExport() {
-		return SymKindExtdef
-	}
-	return SymKindLocal
-}
-
-func addsym(ctxt *Link, s *sym.Symbol, name string, type_ SymbolType, addr int64, gotype *sym.Symbol) {
-	if s == nil {
-		return
-	}
-
-	switch type_ {
-	default:
-		return
-
-	case DataSym, BSSSym, TextSym:
-		break
-	}
-
-	if sortsym != nil {
-		sortsym[nsortsym] = s
-		nkind[symkind(s)]++
-	}
-
-	nsortsym++
-}
-
-type machoscmp []*sym.Symbol
-
-func (x machoscmp) Len() int {
-	return len(x)
-}
-
-func (x machoscmp) Swap(i, j int) {
-	x[i], x[j] = x[j], x[i]
-}
-
-func (x machoscmp) Less(i, j int) bool {
-	s1 := x[i]
-	s2 := x[j]
-
-	k1 := symkind(s1)
-	k2 := symkind(s2)
-	if k1 != k2 {
-		return k1 < k2
-	}
-
-	return s1.Extname() < s2.Extname()
-}
-
-func machogenasmsym(ctxt *Link) {
-	genasmsym(ctxt, addsym)
-	for _, s := range ctxt.Syms.Allsym {
-		// Some 64-bit functions have a "$INODE64" or "$INODE64$UNIX2003" suffix.
-		if s.Type == sym.SDYNIMPORT && s.Dynimplib() == "/usr/lib/libSystem.B.dylib" {
-			// But only on macOS.
-			if machoPlatform == PLATFORM_MACOS {
-				switch n := s.Extname(); n {
-				case "fdopendir":
-					switch objabi.GOARCH {
-					case "amd64":
-						s.SetExtname(n + "$INODE64")
-					case "386":
-						s.SetExtname(n + "$INODE64$UNIX2003")
-					}
-				case "readdir_r", "getfsstat":
-					switch objabi.GOARCH {
-					case "amd64", "386":
-						s.SetExtname(n + "$INODE64")
-					}
-				}
-			}
-		}
-
-		if s.Type == sym.SDYNIMPORT || s.Type == sym.SHOSTOBJ || s.Type == sym.SUNDEFEXT {
-			if s.Attr.Reachable() {
-				addsym(ctxt, s, "", DataSym, 0, nil)
-			}
-		}
-	}
-}
-
-func machosymorder(ctxt *Link) {
-	// On Mac OS X Mountain Lion, we must sort exported symbols
-	// So we sort them here and pre-allocate dynid for them
-	// See https://golang.org/issue/4029
-	for i := range dynexp {
-		dynexp[i].Attr |= sym.AttrReachable
-	}
-	machogenasmsym(ctxt)
-	sortsym = make([]*sym.Symbol, nsortsym)
-	nsortsym = 0
-	machogenasmsym(ctxt)
-	sort.Sort(machoscmp(sortsym[:nsortsym]))
-	for i := 0; i < nsortsym; i++ {
-		sortsym[i].Dynid = int32(i)
-	}
-}
-
-// machoShouldExport reports whether a symbol needs to be exported.
-//
-// When dynamically linking, all non-local variables and plugin-exported
-// symbols need to be exported.
-func machoShouldExport(ctxt *Link, s *sym.Symbol) bool {
-	if !ctxt.DynlinkingGo() || s.Attr.Local() {
-		return false
-	}
-	if ctxt.BuildMode == BuildModePlugin && strings.HasPrefix(s.Extname(), objabi.PathToPrefix(*flagPluginPath)) {
-		return true
-	}
-	if strings.HasPrefix(s.Name, "go.itab.") {
-		return true
-	}
-	if strings.HasPrefix(s.Name, "type.") && !strings.HasPrefix(s.Name, "type..") {
-		// reduce runtime typemap pressure, but do not
-		// export alg functions (type..*), as these
-		// appear in pclntable.
-		return true
-	}
-	if strings.HasPrefix(s.Name, "go.link.pkghash") {
-		return true
-	}
-	return s.Type >= sym.SFirstWritable // only writable sections
-}
-
-func machosymtab(ctxt *Link) {
-	symtab := ctxt.Syms.Lookup(".machosymtab", 0)
-	symstr := ctxt.Syms.Lookup(".machosymstr", 0)
-
-	for i := 0; i < nsortsym; i++ {
-		s := sortsym[i]
-		symtab.AddUint32(ctxt.Arch, uint32(symstr.Size))
-
-		export := machoShouldExport(ctxt, s)
-		isGoSymbol := strings.Contains(s.Extname(), ".")
-
-		// In normal buildmodes, only add _ to C symbols, as
-		// Go symbols have dot in the name.
-		//
-		// Do not export C symbols in plugins, as runtime C
-		// symbols like crosscall2 are in pclntab and end up
-		// pointing at the host binary, breaking unwinding.
-		// See Issue #18190.
-		cexport := !isGoSymbol && (ctxt.BuildMode != BuildModePlugin || onlycsymbol(s))
-		if cexport || export || isGoSymbol {
-			symstr.AddUint8('_')
-		}
-
-		// replace "·" as ".", because DTrace cannot handle it.
-		Addstring(symstr, strings.Replace(s.Extname(), "·", ".", -1))
-
-		if s.Type == sym.SDYNIMPORT || s.Type == sym.SHOSTOBJ || s.Type == sym.SUNDEFEXT {
-			symtab.AddUint8(0x01)                             // type N_EXT, external symbol
-			symtab.AddUint8(0)                                // no section
-			symtab.AddUint16(ctxt.Arch, 0)                    // desc
-			symtab.AddUintXX(ctxt.Arch, 0, ctxt.Arch.PtrSize) // no value
-		} else {
-			if s.Attr.CgoExport() || export {
-				symtab.AddUint8(0x0f)
-			} else {
-				symtab.AddUint8(0x0e)
-			}
-			o := s
-			for o.Outer != nil {
-				o = o.Outer
-			}
-			if o.Sect == nil {
-				Errorf(s, "missing section for symbol")
-				symtab.AddUint8(0)
-			} else {
-				symtab.AddUint8(uint8(o.Sect.Extnum))
-			}
-			symtab.AddUint16(ctxt.Arch, 0) // desc
-			symtab.AddUintXX(ctxt.Arch, uint64(Symaddr(s)), ctxt.Arch.PtrSize)
-		}
-	}
-}
-
-func machodysymtab(ctxt *Link) {
-	ml := newMachoLoad(ctxt.Arch, LC_DYSYMTAB, 18)
-
-	n := 0
-	ml.data[0] = uint32(n)                   /* ilocalsym */
-	ml.data[1] = uint32(nkind[SymKindLocal]) /* nlocalsym */
-	n += nkind[SymKindLocal]
-
-	ml.data[2] = uint32(n)                    /* iextdefsym */
-	ml.data[3] = uint32(nkind[SymKindExtdef]) /* nextdefsym */
-	n += nkind[SymKindExtdef]
-
-	ml.data[4] = uint32(n)                   /* iundefsym */
-	ml.data[5] = uint32(nkind[SymKindUndef]) /* nundefsym */
-
-	ml.data[6] = 0  /* tocoffset */
-	ml.data[7] = 0  /* ntoc */
-	ml.data[8] = 0  /* modtaboff */
-	ml.data[9] = 0  /* nmodtab */
-	ml.data[10] = 0 /* extrefsymoff */
-	ml.data[11] = 0 /* nextrefsyms */
-
-	// must match domacholink below
-	s1 := ctxt.Syms.Lookup(".machosymtab", 0)
-
-	s2 := ctxt.Syms.Lookup(".linkedit.plt", 0)
-	s3 := ctxt.Syms.Lookup(".linkedit.got", 0)
-	ml.data[12] = uint32(linkoff + s1.Size)       /* indirectsymoff */
-	ml.data[13] = uint32((s2.Size + s3.Size) / 4) /* nindirectsyms */
-
-	ml.data[14] = 0 /* extreloff */
-	ml.data[15] = 0 /* nextrel */
-	ml.data[16] = 0 /* locreloff */
-	ml.data[17] = 0 /* nlocrel */
-}
-
-func Domacholink(ctxt *Link) int64 {
-	machosymtab(ctxt)
-
-	// write data that will be linkedit section
-	s1 := ctxt.Syms.Lookup(".machosymtab", 0)
-
-	s2 := ctxt.Syms.Lookup(".linkedit.plt", 0)
-	s3 := ctxt.Syms.Lookup(".linkedit.got", 0)
-	s4 := ctxt.Syms.Lookup(".machosymstr", 0)
-
-	// Force the linkedit section to end on a 16-byte
-	// boundary. This allows pure (non-cgo) Go binaries
-	// to be code signed correctly.
-	//
-	// Apple's codesign_allocate (a helper utility for
-	// the codesign utility) can do this fine itself if
-	// it is run on a dynamic Mach-O binary. However,
-	// when it is run on a pure (non-cgo) Go binary, where
-	// the linkedit section is mostly empty, it fails to
-	// account for the extra padding that it itself adds
-	// when adding the LC_CODE_SIGNATURE load command
-	// (which must be aligned on a 16-byte boundary).
-	//
-	// By forcing the linkedit section to end on a 16-byte
-	// boundary, codesign_allocate will not need to apply
-	// any alignment padding itself, working around the
-	// issue.
-	for s4.Size%16 != 0 {
-		s4.AddUint8(0)
-	}
-
-	size := int(s1.Size + s2.Size + s3.Size + s4.Size)
-
-	if size > 0 {
-		linkoff = Rnd(int64(uint64(HEADR)+Segtext.Length), int64(*FlagRound)) + Rnd(int64(Segdata.Filelen), int64(*FlagRound)) + Rnd(int64(Segdwarf.Filelen), int64(*FlagRound))
-		ctxt.Out.SeekSet(linkoff)
-
-		ctxt.Out.Write(s1.P[:s1.Size])
-		ctxt.Out.Write(s2.P[:s2.Size])
-		ctxt.Out.Write(s3.P[:s3.Size])
-		ctxt.Out.Write(s4.P[:s4.Size])
-	}
-
-	return Rnd(int64(size), int64(*FlagRound))
-}
-
-func machorelocsect(ctxt *Link, sect *sym.Section, syms []*sym.Symbol) {
-	// If main section has no bits, nothing to relocate.
-	if sect.Vaddr >= sect.Seg.Vaddr+sect.Seg.Filelen {
-		return
-	}
-
-	sect.Reloff = uint64(ctxt.Out.Offset())
-	for i, s := range syms {
-		if !s.Attr.Reachable() {
-			continue
-		}
-		if uint64(s.Value) >= sect.Vaddr {
-			syms = syms[i:]
-			break
-		}
-	}
-
-	eaddr := int32(sect.Vaddr + sect.Length)
-	for _, s := range syms {
-		if !s.Attr.Reachable() {
-			continue
-		}
-		if s.Value >= int64(eaddr) {
-			break
-		}
-		for ri := range s.R {
-			r := &s.R[ri]
-			if r.Done {
-				continue
-			}
-			if r.Xsym == nil {
-				Errorf(s, "missing xsym in relocation")
-				continue
-			}
-			if !r.Xsym.Attr.Reachable() {
-				Errorf(s, "unreachable reloc %d (%s) target %v", r.Type, sym.RelocName(ctxt.Arch, r.Type), r.Xsym.Name)
-			}
-			if !thearch.Machoreloc1(ctxt.Arch, ctxt.Out, s, r, int64(uint64(s.Value+int64(r.Off))-sect.Vaddr)) {
-				Errorf(s, "unsupported obj reloc %d (%s)/%d to %s", r.Type, sym.RelocName(ctxt.Arch, r.Type), r.Siz, r.Sym.Name)
-			}
-		}
-	}
-
-	sect.Rellen = uint64(ctxt.Out.Offset()) - sect.Reloff
-}
-
-func Machoemitreloc(ctxt *Link) {
-	for ctxt.Out.Offset()&7 != 0 {
-		ctxt.Out.Write8(0)
-	}
-
-	machorelocsect(ctxt, Segtext.Sections[0], ctxt.Textp)
-	for _, sect := range Segtext.Sections[1:] {
-		machorelocsect(ctxt, sect, datap)
-	}
-	for _, sect := range Segdata.Sections {
-		machorelocsect(ctxt, sect, datap)
-	}
-	for _, sect := range Segdwarf.Sections {
-		machorelocsect(ctxt, sect, dwarfp)
-	}
-}
-
-// hostobjMachoPlatform returns the first platform load command found
-// in the host object, if any.
-func hostobjMachoPlatform(h *Hostobj) (*MachoPlatformLoad, error) {
-	f, err := os.Open(h.file)
-	if err != nil {
-		return nil, fmt.Errorf("%s: failed to open host object: %v\n", h.file, err)
-	}
-	defer f.Close()
-	sr := io.NewSectionReader(f, h.off, h.length)
-	m, err := macho.NewFile(sr)
-	if err != nil {
-		// Not a valid Mach-O file.
-		return nil, nil
-	}
-	return peekMachoPlatform(m)
-}
-
-// peekMachoPlatform returns the first LC_VERSION_MIN_* or LC_BUILD_VERSION
-// load command found in the Mach-O file, if any.
-func peekMachoPlatform(m *macho.File) (*MachoPlatformLoad, error) {
-	for _, cmd := range m.Loads {
-		raw := cmd.Raw()
-		ml := MachoLoad{
-			type_: m.ByteOrder.Uint32(raw),
-		}
-		// Skip the type and command length.
-		data := raw[8:]
-		var p MachoPlatform
-		switch ml.type_ {
-		case LC_VERSION_MIN_IPHONEOS:
-			p = PLATFORM_IOS
-		case LC_VERSION_MIN_MACOSX:
-			p = PLATFORM_MACOS
-		case LC_VERSION_MIN_WATCHOS:
-			p = PLATFORM_WATCHOS
-		case LC_VERSION_MIN_TVOS:
-			p = PLATFORM_TVOS
-		case LC_BUILD_VERSION:
-			p = MachoPlatform(m.ByteOrder.Uint32(data))
-		default:
-			continue
-		}
-		ml.data = make([]uint32, len(data)/4)
-		r := bytes.NewReader(data)
-		if err := binary.Read(r, m.ByteOrder, &ml.data); err != nil {
-			return nil, err
-		}
-		return &MachoPlatformLoad{
-			platform: p,
-			cmd:      ml,
-		}, nil
-	}
-	return nil, nil
-}
diff --git a/src/cmd/oldlink/internal/ld/macho_combine_dwarf.go b/src/cmd/oldlink/internal/ld/macho_combine_dwarf.go
deleted file mode 100644
index 9d9f916..0000000
--- a/src/cmd/oldlink/internal/ld/macho_combine_dwarf.go
+++ /dev/null
@@ -1,462 +0,0 @@
-// Copyright 2015 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 (
-	"bytes"
-	"compress/zlib"
-	"debug/macho"
-	"encoding/binary"
-	"fmt"
-	"io"
-	"os"
-	"reflect"
-	"unsafe"
-)
-
-const (
-	pageAlign = 12 // 4096 = 1 << 12
-)
-
-type loadCmd struct {
-	Cmd macho.LoadCmd
-	Len uint32
-}
-
-type dyldInfoCmd struct {
-	Cmd                      macho.LoadCmd
-	Len                      uint32
-	RebaseOff, RebaseLen     uint32
-	BindOff, BindLen         uint32
-	WeakBindOff, WeakBindLen uint32
-	LazyBindOff, LazyBindLen uint32
-	ExportOff, ExportLen     uint32
-}
-
-type linkEditDataCmd struct {
-	Cmd              macho.LoadCmd
-	Len              uint32
-	DataOff, DataLen uint32
-}
-
-type encryptionInfoCmd struct {
-	Cmd                macho.LoadCmd
-	Len                uint32
-	CryptOff, CryptLen uint32
-	CryptId            uint32
-}
-
-type loadCmdReader struct {
-	offset, next int64
-	f            *os.File
-	order        binary.ByteOrder
-}
-
-func (r *loadCmdReader) Next() (loadCmd, error) {
-	var cmd loadCmd
-
-	r.offset = r.next
-	if _, err := r.f.Seek(r.offset, 0); err != nil {
-		return cmd, err
-	}
-	if err := binary.Read(r.f, r.order, &cmd); err != nil {
-		return cmd, err
-	}
-	r.next = r.offset + int64(cmd.Len)
-	return cmd, nil
-}
-
-func (r loadCmdReader) ReadAt(offset int64, data interface{}) error {
-	if _, err := r.f.Seek(r.offset+offset, 0); err != nil {
-		return err
-	}
-	return binary.Read(r.f, r.order, data)
-}
-
-func (r loadCmdReader) WriteAt(offset int64, data interface{}) error {
-	if _, err := r.f.Seek(r.offset+offset, 0); err != nil {
-		return err
-	}
-	return binary.Write(r.f, r.order, data)
-}
-
-// machoCombineDwarf merges dwarf info generated by dsymutil into a macho executable.
-//
-// With internal linking, DWARF is embedded into the executable, this lets us do the
-// same for external linking.
-// exef is the file of the executable with no DWARF. It must have enough room in the macho
-// header to add the DWARF sections. (Use ld's -headerpad option)
-// exem is the macho representation of exef.
-// dsym is the path to the macho file containing DWARF from dsymutil.
-// outexe is the path where the combined executable should be saved.
-func machoCombineDwarf(ctxt *Link, exef *os.File, exem *macho.File, dsym, outexe string) error {
-	dwarff, err := os.Open(dsym)
-	if err != nil {
-		return err
-	}
-	defer dwarff.Close()
-	outf, err := os.OpenFile(outexe, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0755)
-	if err != nil {
-		return err
-	}
-	defer outf.Close()
-	dwarfm, err := macho.NewFile(dwarff)
-	if err != nil {
-		return err
-	}
-	defer dwarfm.Close()
-
-	// The string table needs to be the last thing in the file
-	// for code signing to work. So we'll need to move the
-	// linkedit section, but all the others can be copied directly.
-	linkseg := exem.Segment("__LINKEDIT")
-	if linkseg == nil {
-		return fmt.Errorf("missing __LINKEDIT segment")
-	}
-
-	if _, err := exef.Seek(0, 0); err != nil {
-		return err
-	}
-	if _, err := io.CopyN(outf, exef, int64(linkseg.Offset)); err != nil {
-		return err
-	}
-
-	realdwarf := dwarfm.Segment("__DWARF")
-	if realdwarf == nil {
-		return fmt.Errorf("missing __DWARF segment")
-	}
-
-	// Try to compress the DWARF sections. This includes some Apple
-	// proprietary sections like __apple_types.
-	compressedSects, compressedBytes, err := machoCompressSections(ctxt, dwarfm)
-	if err != nil {
-		return err
-	}
-
-	// Now copy the dwarf data into the output.
-	// Kernel requires all loaded segments to be page-aligned in the file,
-	// even though we mark this one as being 0 bytes of virtual address space.
-	dwarfstart := machoCalcStart(realdwarf.Offset, linkseg.Offset, pageAlign)
-	if _, err := outf.Seek(dwarfstart, 0); err != nil {
-		return err
-	}
-
-	if _, err := dwarff.Seek(int64(realdwarf.Offset), 0); err != nil {
-		return err
-	}
-
-	// Write out the compressed sections, or the originals if we gave up
-	// on compressing them.
-	var dwarfsize uint64
-	if compressedBytes != nil {
-		dwarfsize = uint64(len(compressedBytes))
-		if _, err := outf.Write(compressedBytes); err != nil {
-			return err
-		}
-	} else {
-		if _, err := io.CopyN(outf, dwarff, int64(realdwarf.Filesz)); err != nil {
-			return err
-		}
-		dwarfsize = realdwarf.Filesz
-	}
-
-	// And finally the linkedit section.
-	if _, err := exef.Seek(int64(linkseg.Offset), 0); err != nil {
-		return err
-	}
-	linkstart := machoCalcStart(linkseg.Offset, uint64(dwarfstart)+dwarfsize, pageAlign)
-	if _, err := outf.Seek(linkstart, 0); err != nil {
-		return err
-	}
-	if _, err := io.Copy(outf, exef); err != nil {
-		return err
-	}
-
-	// Now we need to update the headers.
-	textsect := exem.Section("__text")
-	if textsect == nil {
-		return fmt.Errorf("missing __text section")
-	}
-
-	cmdOffset := unsafe.Sizeof(exem.FileHeader)
-	if is64bit := exem.Magic == macho.Magic64; is64bit {
-		// mach_header_64 has one extra uint32.
-		cmdOffset += unsafe.Sizeof(exem.Magic)
-	}
-	dwarfCmdOffset := uint32(cmdOffset) + exem.FileHeader.Cmdsz
-	availablePadding := textsect.Offset - dwarfCmdOffset
-	if availablePadding < realdwarf.Len {
-		return fmt.Errorf("no room to add dwarf info. Need at least %d padding bytes, found %d", realdwarf.Len, availablePadding)
-	}
-	// First, copy the dwarf load command into the header. It will be
-	// updated later with new offsets and lengths as necessary.
-	if _, err := outf.Seek(int64(dwarfCmdOffset), 0); err != nil {
-		return err
-	}
-	if _, err := io.CopyN(outf, bytes.NewReader(realdwarf.Raw()), int64(realdwarf.Len)); err != nil {
-		return err
-	}
-	if _, err := outf.Seek(int64(unsafe.Offsetof(exem.FileHeader.Ncmd)), 0); err != nil {
-		return err
-	}
-	if err := binary.Write(outf, exem.ByteOrder, exem.Ncmd+1); err != nil {
-		return err
-	}
-	if err := binary.Write(outf, exem.ByteOrder, exem.Cmdsz+realdwarf.Len); err != nil {
-		return err
-	}
-
-	reader := loadCmdReader{next: int64(cmdOffset), f: outf, order: exem.ByteOrder}
-	for i := uint32(0); i < exem.Ncmd; i++ {
-		cmd, err := reader.Next()
-		if err != nil {
-			return err
-		}
-		linkoffset := uint64(linkstart) - linkseg.Offset
-		switch cmd.Cmd {
-		case macho.LoadCmdSegment64:
-			err = machoUpdateSegment(reader, linkseg, linkoffset, &macho.Segment64{}, &macho.Section64{})
-		case macho.LoadCmdSegment:
-			err = machoUpdateSegment(reader, linkseg, linkoffset, &macho.Segment32{}, &macho.Section32{})
-		case LC_DYLD_INFO, LC_DYLD_INFO_ONLY:
-			err = machoUpdateLoadCommand(reader, linkseg, linkoffset, &dyldInfoCmd{}, "RebaseOff", "BindOff", "WeakBindOff", "LazyBindOff", "ExportOff")
-		case macho.LoadCmdSymtab:
-			err = machoUpdateLoadCommand(reader, linkseg, linkoffset, &macho.SymtabCmd{}, "Symoff", "Stroff")
-		case macho.LoadCmdDysymtab:
-			err = machoUpdateLoadCommand(reader, linkseg, linkoffset, &macho.DysymtabCmd{}, "Tocoffset", "Modtaboff", "Extrefsymoff", "Indirectsymoff", "Extreloff", "Locreloff")
-		case LC_CODE_SIGNATURE, LC_SEGMENT_SPLIT_INFO, LC_FUNCTION_STARTS, LC_DATA_IN_CODE, LC_DYLIB_CODE_SIGN_DRS:
-			err = machoUpdateLoadCommand(reader, linkseg, linkoffset, &linkEditDataCmd{}, "DataOff")
-		case LC_ENCRYPTION_INFO, LC_ENCRYPTION_INFO_64:
-			err = machoUpdateLoadCommand(reader, linkseg, linkoffset, &encryptionInfoCmd{}, "CryptOff")
-		case macho.LoadCmdDylib, macho.LoadCmdThread, macho.LoadCmdUnixThread, LC_PREBOUND_DYLIB, LC_UUID, LC_VERSION_MIN_MACOSX, LC_VERSION_MIN_IPHONEOS, LC_SOURCE_VERSION, LC_MAIN, LC_LOAD_DYLINKER, LC_LOAD_WEAK_DYLIB, LC_REEXPORT_DYLIB, LC_RPATH, LC_ID_DYLIB, LC_SYMSEG, LC_LOADFVMLIB, LC_IDFVMLIB, LC_IDENT, LC_FVMFILE, LC_PREPAGE, LC_ID_DYLINKER, LC_ROUTINES, LC_SUB_FRAMEWORK, LC_SUB_UMBRELLA, LC_SUB_CLIENT, LC_SUB_LIBRARY, LC_TWOLEVEL_HINTS, LC_PREBIND_CKSUM, LC_ROUTINES_64, LC_LAZY_LOAD_DYLIB, LC_LOAD_UPWARD_DYLIB, LC_DYLD_ENVIRONMENT, LC_LINKER_OPTION, LC_LINKER_OPTIMIZATION_HINT, LC_VERSION_MIN_TVOS, LC_VERSION_MIN_WATCHOS, LC_VERSION_NOTE, LC_BUILD_VERSION:
-			// Nothing to update
-		default:
-			err = fmt.Errorf("unknown load command 0x%x (%s)", int(cmd.Cmd), cmd.Cmd)
-		}
-		if err != nil {
-			return err
-		}
-	}
-	// Do the final update of the DWARF segment's load command.
-	return machoUpdateDwarfHeader(&reader, compressedSects, dwarfsize, dwarfstart, realdwarf)
-}
-
-// machoCompressSections tries to compress the DWARF segments in dwarfm,
-// returning the updated sections and segment contents, nils if the sections
-// weren't compressed, or an error if there was a problem reading dwarfm.
-func machoCompressSections(ctxt *Link, dwarfm *macho.File) ([]*macho.Section, []byte, error) {
-	if !ctxt.compressDWARF {
-		return nil, nil, nil
-	}
-
-	dwarfseg := dwarfm.Segment("__DWARF")
-	var sects []*macho.Section
-	var buf bytes.Buffer
-
-	for _, sect := range dwarfm.Sections {
-		if sect.Seg != "__DWARF" {
-			continue
-		}
-
-		// As of writing, there are no relocations in dsymutil's output
-		// so there's no point in worrying about them. Bail out if that
-		// changes.
-		if sect.Nreloc != 0 {
-			return nil, nil, nil
-		}
-
-		data, err := sect.Data()
-		if err != nil {
-			return nil, nil, err
-		}
-
-		compressed, contents, err := machoCompressSection(data)
-		if err != nil {
-			return nil, nil, err
-		}
-
-		newSec := *sect
-		newSec.Offset = uint32(dwarfseg.Offset) + uint32(buf.Len())
-		newSec.Addr = dwarfseg.Addr + uint64(buf.Len())
-		if compressed {
-			newSec.Name = "__z" + sect.Name[2:]
-			newSec.Size = uint64(len(contents))
-		}
-		sects = append(sects, &newSec)
-		buf.Write(contents)
-	}
-	return sects, buf.Bytes(), nil
-}
-
-// machoCompressSection compresses secBytes if it results in less data.
-func machoCompressSection(sectBytes []byte) (compressed bool, contents []byte, err error) {
-	var buf bytes.Buffer
-	buf.WriteString("ZLIB")
-	var sizeBytes [8]byte
-	binary.BigEndian.PutUint64(sizeBytes[:], uint64(len(sectBytes)))
-	buf.Write(sizeBytes[:])
-
-	z := zlib.NewWriter(&buf)
-	if _, err := z.Write(sectBytes); err != nil {
-		return false, nil, err
-	}
-	if err := z.Close(); err != nil {
-		return false, nil, err
-	}
-	if buf.Len() >= len(sectBytes) {
-		return false, sectBytes, nil
-	}
-	return true, buf.Bytes(), nil
-}
-
-// machoUpdateSegment updates the load command for a moved segment.
-// Only the linkedit segment should move, and it should have 0 sections.
-// seg should be a macho.Segment32 or macho.Segment64 as appropriate.
-// sect should be a macho.Section32 or macho.Section64 as appropriate.
-func machoUpdateSegment(r loadCmdReader, linkseg *macho.Segment, linkoffset uint64, seg, sect interface{}) error {
-	if err := r.ReadAt(0, seg); err != nil {
-		return err
-	}
-	segValue := reflect.ValueOf(seg)
-	offset := reflect.Indirect(segValue).FieldByName("Offset")
-
-	// Only the linkedit segment moved, anything before that is fine.
-	if offset.Uint() < linkseg.Offset {
-		return nil
-	}
-	offset.SetUint(offset.Uint() + linkoffset)
-	if err := r.WriteAt(0, seg); err != nil {
-		return err
-	}
-	// There shouldn't be any sections, but just to make sure...
-	return machoUpdateSections(r, segValue, reflect.ValueOf(sect), linkoffset, nil)
-}
-
-func machoUpdateSections(r loadCmdReader, seg, sect reflect.Value, deltaOffset uint64, compressedSects []*macho.Section) error {
-	iseg := reflect.Indirect(seg)
-	nsect := iseg.FieldByName("Nsect").Uint()
-	if nsect == 0 {
-		return nil
-	}
-	sectOffset := int64(iseg.Type().Size())
-
-	isect := reflect.Indirect(sect)
-	offsetField := isect.FieldByName("Offset")
-	reloffField := isect.FieldByName("Reloff")
-	addrField := isect.FieldByName("Addr")
-	nameField := isect.FieldByName("Name")
-	sizeField := isect.FieldByName("Size")
-	sectSize := int64(isect.Type().Size())
-	for i := uint64(0); i < nsect; i++ {
-		if err := r.ReadAt(sectOffset, sect.Interface()); err != nil {
-			return err
-		}
-		if compressedSects != nil {
-			cSect := compressedSects[i]
-			var name [16]byte
-			copy(name[:], []byte(cSect.Name))
-			nameField.Set(reflect.ValueOf(name))
-			sizeField.SetUint(cSect.Size)
-			if cSect.Offset != 0 {
-				offsetField.SetUint(uint64(cSect.Offset) + deltaOffset)
-			}
-			if cSect.Addr != 0 {
-				addrField.SetUint(cSect.Addr)
-			}
-		} else {
-			if offsetField.Uint() != 0 {
-				offsetField.SetUint(offsetField.Uint() + deltaOffset)
-			}
-			if reloffField.Uint() != 0 {
-				reloffField.SetUint(reloffField.Uint() + deltaOffset)
-			}
-			if addrField.Uint() != 0 {
-				addrField.SetUint(addrField.Uint())
-			}
-		}
-		if err := r.WriteAt(sectOffset, sect.Interface()); err != nil {
-			return err
-		}
-		sectOffset += sectSize
-	}
-	return nil
-}
-
-// machoUpdateDwarfHeader updates the DWARF segment load command.
-func machoUpdateDwarfHeader(r *loadCmdReader, compressedSects []*macho.Section, dwarfsize uint64, dwarfstart int64, realdwarf *macho.Segment) error {
-	var seg, sect interface{}
-	cmd, err := r.Next()
-	if err != nil {
-		return err
-	}
-	if cmd.Cmd == macho.LoadCmdSegment64 {
-		seg = new(macho.Segment64)
-		sect = new(macho.Section64)
-	} else {
-		seg = new(macho.Segment32)
-		sect = new(macho.Section32)
-	}
-	if err := r.ReadAt(0, seg); err != nil {
-		return err
-	}
-	segv := reflect.ValueOf(seg).Elem()
-	segv.FieldByName("Offset").SetUint(uint64(dwarfstart))
-
-	if compressedSects != nil {
-		var segSize uint64
-		for _, newSect := range compressedSects {
-			segSize += newSect.Size
-		}
-		segv.FieldByName("Filesz").SetUint(segSize)
-	} else {
-		segv.FieldByName("Filesz").SetUint(dwarfsize)
-	}
-
-	// We want the DWARF segment to be considered non-loadable, so
-	// force vmaddr and vmsize to zero. In addition, set the initial
-	// protection to zero so as to make the dynamic loader happy,
-	// since otherwise it may complain that that the vm size and file
-	// size don't match for the segment. See issues 21647 and 32673
-	// for more context. Also useful to refer to the Apple dynamic
-	// loader source, specifically ImageLoaderMachO::sniffLoadCommands
-	// in ImageLoaderMachO.cpp (various versions can be found online, see
-	// https://opensource.apple.com/source/dyld/dyld-519.2.2/src/ImageLoaderMachO.cpp.auto.html
-	// as one example).
-	segv.FieldByName("Addr").SetUint(0)
-	segv.FieldByName("Memsz").SetUint(0)
-	segv.FieldByName("Prot").SetUint(0)
-
-	if err := r.WriteAt(0, seg); err != nil {
-		return err
-	}
-	return machoUpdateSections(*r, segv, reflect.ValueOf(sect), uint64(dwarfstart)-realdwarf.Offset, compressedSects)
-}
-
-func machoUpdateLoadCommand(r loadCmdReader, linkseg *macho.Segment, linkoffset uint64, cmd interface{}, fields ...string) error {
-	if err := r.ReadAt(0, cmd); err != nil {
-		return err
-	}
-	value := reflect.Indirect(reflect.ValueOf(cmd))
-
-	for _, name := range fields {
-		field := value.FieldByName(name)
-		if fieldval := field.Uint(); fieldval >= linkseg.Offset {
-			field.SetUint(fieldval + linkoffset)
-		}
-	}
-	if err := r.WriteAt(0, cmd); err != nil {
-		return err
-	}
-	return nil
-}
-
-func machoCalcStart(origAddr, newAddr uint64, alignExp uint32) int64 {
-	align := uint64(1 << alignExp)
-	origMod, newMod := origAddr%align, newAddr%align
-	if origMod == newMod {
-		return int64(newAddr)
-	}
-	return int64(newAddr + align + origMod - newMod)
-}
diff --git a/src/cmd/oldlink/internal/ld/main.go b/src/cmd/oldlink/internal/ld/main.go
deleted file mode 100644
index fdbb1de..0000000
--- a/src/cmd/oldlink/internal/ld/main.go
+++ /dev/null
@@ -1,338 +0,0 @@
-// Inferno utils/6l/obj.c
-// https://bitbucket.org/inferno-os/inferno-os/src/master/utils/6l/obj.c
-//
-//	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
-
-import (
-	"bufio"
-	"cmd/internal/objabi"
-	"cmd/internal/sys"
-	"cmd/oldlink/internal/sym"
-	"flag"
-	"log"
-	"os"
-	"runtime"
-	"runtime/pprof"
-	"strings"
-)
-
-var (
-	pkglistfornote []byte
-	windowsgui     bool // writes a "GUI binary" instead of a "console binary"
-	ownTmpDir      bool // set to true if tmp dir created by linker (e.g. no -tmpdir)
-)
-
-func init() {
-	flag.Var(&rpath, "r", "set the ELF dynamic linker search `path` to dir1:dir2:...")
-}
-
-// Flags used by the linker. The exported flags are used by the architecture-specific packages.
-var (
-	flagBuildid = flag.String("buildid", "", "record `id` as Go toolchain build id")
-
-	flagOutfile    = flag.String("o", "", "write output to `file`")
-	flagPluginPath = flag.String("pluginpath", "", "full path name for plugin")
-
-	flagInstallSuffix = flag.String("installsuffix", "", "set package directory `suffix`")
-	flagDumpDep       = flag.Bool("dumpdep", false, "dump symbol dependency graph")
-	flagRace          = flag.Bool("race", false, "enable race detector")
-	flagMsan          = flag.Bool("msan", false, "enable MSan interface")
-
-	flagFieldTrack = flag.String("k", "", "set field tracking `symbol`")
-	flagLibGCC     = flag.String("libgcc", "", "compiler support lib for internal linking; use \"none\" to disable")
-	flagTmpdir     = flag.String("tmpdir", "", "use `directory` for temporary files")
-
-	flagExtld      = flag.String("extld", "", "use `linker` when linking in external mode")
-	flagExtldflags = flag.String("extldflags", "", "pass `flags` to external linker")
-	flagExtar      = flag.String("extar", "", "archive program for buildmode=c-archive")
-
-	flagA           = flag.Bool("a", false, "disassemble output")
-	FlagC           = flag.Bool("c", false, "dump call graph")
-	FlagD           = flag.Bool("d", false, "disable dynamic executable")
-	flagF           = flag.Bool("f", false, "ignore version mismatch")
-	flagG           = flag.Bool("g", false, "disable go package data checks")
-	flagH           = flag.Bool("h", false, "halt on error")
-	flagN           = flag.Bool("n", false, "dump symbol table")
-	FlagS           = flag.Bool("s", false, "disable symbol table")
-	flagU           = flag.Bool("u", false, "reject unsafe packages")
-	FlagW           = flag.Bool("w", false, "disable DWARF generation")
-	Flag8           bool // use 64-bit addresses in symbol table
-	flagInterpreter = flag.String("I", "", "use `linker` as ELF dynamic linker")
-	FlagDebugTramp  = flag.Int("debugtramp", 0, "debug trampolines")
-	FlagStrictDups  = flag.Int("strictdups", 0, "sanity check duplicate symbol contents during object file reading (1=warn 2=err).")
-	flagNewobj      = flag.Bool("newobj", false, "use new object file format")
-
-	FlagRound       = flag.Int("R", -1, "set address rounding `quantum`")
-	FlagTextAddr    = flag.Int64("T", -1, "set text segment `address`")
-	flagEntrySymbol = flag.String("E", "", "set `entry` symbol name")
-
-	cpuprofile     = flag.String("cpuprofile", "", "write cpu profile to `file`")
-	memprofile     = flag.String("memprofile", "", "write memory profile to `file`")
-	memprofilerate = flag.Int64("memprofilerate", 0, "set runtime.MemProfileRate to `rate`")
-)
-
-// Main is the main entry point for the linker code.
-func Main(arch *sys.Arch, theArch Arch) {
-	thearch = theArch
-	ctxt := linknew(arch)
-	ctxt.Bso = bufio.NewWriter(os.Stdout)
-
-	// For testing behavior of go command when tools crash silently.
-	// Undocumented, not in standard flag parser to avoid
-	// exposing in usage message.
-	for _, arg := range os.Args {
-		if arg == "-crash_for_testing" {
-			os.Exit(2)
-		}
-	}
-
-	final := gorootFinal()
-	addstrdata1(ctxt, "runtime/internal/sys.DefaultGoroot="+final)
-	addstrdata1(ctxt, "cmd/internal/objabi.defaultGOROOT="+final)
-
-	// TODO(matloob): define these above and then check flag values here
-	if ctxt.Arch.Family == sys.AMD64 && objabi.GOOS == "plan9" {
-		flag.BoolVar(&Flag8, "8", false, "use 64-bit addresses in symbol table")
-	}
-	flagHeadType := flag.String("H", "", "set header `type`")
-	flag.BoolVar(&ctxt.linkShared, "linkshared", false, "link against installed Go shared libraries")
-	flag.Var(&ctxt.LinkMode, "linkmode", "set link `mode`")
-	flag.Var(&ctxt.BuildMode, "buildmode", "set build `mode`")
-	flag.BoolVar(&ctxt.compressDWARF, "compressdwarf", true, "compress DWARF if possible")
-	objabi.Flagfn1("B", "add an ELF NT_GNU_BUILD_ID `note` when using ELF", addbuildinfo)
-	objabi.Flagfn1("L", "add specified `directory` to library path", func(a string) { Lflag(ctxt, a) })
-	objabi.AddVersionFlag() // -V
-	objabi.Flagfn1("X", "add string value `definition` of the form importpath.name=value", func(s string) { addstrdata1(ctxt, s) })
-	objabi.Flagcount("v", "print link trace", &ctxt.Debugvlog)
-	objabi.Flagfn1("importcfg", "read import configuration from `file`", ctxt.readImportCfg)
-
-	objabi.Flagparse(usage)
-
-	switch *flagHeadType {
-	case "":
-	case "windowsgui":
-		ctxt.HeadType = objabi.Hwindows
-		windowsgui = true
-	default:
-		if err := ctxt.HeadType.Set(*flagHeadType); err != nil {
-			Errorf(nil, "%v", err)
-			usage()
-		}
-	}
-
-	if objabi.Fieldtrack_enabled != 0 {
-		ctxt.Reachparent = make(map[*sym.Symbol]*sym.Symbol)
-	}
-	checkStrictDups = *FlagStrictDups
-
-	startProfile()
-	if ctxt.BuildMode == BuildModeUnset {
-		ctxt.BuildMode = BuildModeExe
-	}
-
-	if ctxt.BuildMode != BuildModeShared && flag.NArg() != 1 {
-		usage()
-	}
-
-	if *flagOutfile == "" {
-		*flagOutfile = "a.out"
-		if ctxt.HeadType == objabi.Hwindows {
-			*flagOutfile += ".exe"
-		}
-	}
-
-	interpreter = *flagInterpreter
-
-	libinit(ctxt) // creates outfile
-
-	if ctxt.HeadType == objabi.Hunknown {
-		ctxt.HeadType.Set(objabi.GOOS)
-	}
-
-	ctxt.computeTLSOffset()
-	thearch.Archinit(ctxt)
-
-	if ctxt.linkShared && !ctxt.IsELF {
-		Exitf("-linkshared can only be used on elf systems")
-	}
-
-	if ctxt.Debugvlog != 0 {
-		ctxt.Logf("HEADER = -H%d -T0x%x -R0x%x\n", ctxt.HeadType, uint64(*FlagTextAddr), uint32(*FlagRound))
-	}
-
-	switch ctxt.BuildMode {
-	case BuildModeShared:
-		for i := 0; i < flag.NArg(); i++ {
-			arg := flag.Arg(i)
-			parts := strings.SplitN(arg, "=", 2)
-			var pkgpath, file string
-			if len(parts) == 1 {
-				pkgpath, file = "main", arg
-			} else {
-				pkgpath, file = parts[0], parts[1]
-			}
-			pkglistfornote = append(pkglistfornote, pkgpath...)
-			pkglistfornote = append(pkglistfornote, '\n')
-			addlibpath(ctxt, "command line", "command line", file, pkgpath, "")
-		}
-	case BuildModePlugin:
-		addlibpath(ctxt, "command line", "command line", flag.Arg(0), *flagPluginPath, "")
-	default:
-		addlibpath(ctxt, "command line", "command line", flag.Arg(0), "main", "")
-	}
-	ctxt.loadlib()
-
-	deadcode(ctxt)
-	if *flagNewobj {
-		ctxt.loadlibfull() // XXX do it here for now
-	}
-	ctxt.linksetup()
-	ctxt.dostrdata()
-
-	dwarfGenerateDebugInfo(ctxt)
-	if objabi.Fieldtrack_enabled != 0 {
-		fieldtrack(ctxt)
-	}
-	ctxt.mangleTypeSym()
-	ctxt.callgraph()
-
-	ctxt.doelf()
-	if ctxt.HeadType == objabi.Hdarwin {
-		ctxt.domacho()
-	}
-	ctxt.dostkcheck()
-	if ctxt.HeadType == objabi.Hwindows {
-		ctxt.dope()
-		ctxt.windynrelocsyms()
-	}
-	if ctxt.HeadType == objabi.Haix {
-		ctxt.doxcoff()
-	}
-
-	ctxt.addexport()
-	thearch.Gentext(ctxt) // trampolines, call stubs, etc.
-	ctxt.textbuildid()
-	ctxt.textaddress()
-	ctxt.pclntab()
-	ctxt.findfunctab()
-	ctxt.typelink()
-	ctxt.symtab()
-	ctxt.buildinfo()
-	ctxt.dodata()
-	order := ctxt.address()
-	dwarfcompress(ctxt)
-	filesize := ctxt.layout(order)
-
-	// Write out the output file.
-	// It is split into two parts (Asmb and Asmb2). The first
-	// part writes most of the content (sections and segments),
-	// for which we have computed the size and offset, in a
-	// mmap'd region. The second part writes more content, for
-	// which we don't know the size.
-	var outputMmapped bool
-	if ctxt.Arch.Family != sys.Wasm {
-		// Don't mmap if we're building for Wasm. Wasm file
-		// layout is very different so filesize is meaningless.
-		err := ctxt.Out.Mmap(filesize)
-		outputMmapped = err == nil
-	}
-	if outputMmapped {
-		// Asmb will redirect symbols to the output file mmap, and relocations
-		// will be applied directly there.
-		thearch.Asmb(ctxt)
-		ctxt.reloc()
-		ctxt.Out.Munmap()
-	} else {
-		// If we don't mmap, we need to apply relocations before
-		// writing out.
-		ctxt.reloc()
-		thearch.Asmb(ctxt)
-	}
-	thearch.Asmb2(ctxt)
-
-	ctxt.undef()
-	ctxt.hostlink()
-	if ctxt.Debugvlog != 0 {
-		ctxt.Logf("%d symbols\n", len(ctxt.Syms.Allsym))
-		ctxt.Logf("%d liveness data\n", liveness)
-	}
-	ctxt.Bso.Flush()
-	ctxt.archive()
-
-	errorexit()
-}
-
-type Rpath struct {
-	set bool
-	val string
-}
-
-func (r *Rpath) Set(val string) error {
-	r.set = true
-	r.val = val
-	return nil
-}
-
-func (r *Rpath) String() string {
-	return r.val
-}
-
-func startProfile() {
-	if *cpuprofile != "" {
-		f, err := os.Create(*cpuprofile)
-		if err != nil {
-			log.Fatalf("%v", err)
-		}
-		if err := pprof.StartCPUProfile(f); err != nil {
-			log.Fatalf("%v", err)
-		}
-		AtExit(pprof.StopCPUProfile)
-	}
-	if *memprofile != "" {
-		if *memprofilerate != 0 {
-			runtime.MemProfileRate = int(*memprofilerate)
-		}
-		f, err := os.Create(*memprofile)
-		if err != nil {
-			log.Fatalf("%v", err)
-		}
-		AtExit(func() {
-			// Profile all outstanding allocations.
-			runtime.GC()
-			// compilebench parses the memory profile to extract memstats,
-			// which are only written in the legacy pprof format.
-			// See golang.org/issue/18641 and runtime/pprof/pprof.go:writeHeap.
-			const writeLegacyFormat = 1
-			if err := pprof.Lookup("heap").WriteTo(f, writeLegacyFormat); err != nil {
-				log.Fatalf("%v", err)
-			}
-		})
-	}
-}
diff --git a/src/cmd/oldlink/internal/ld/outbuf.go b/src/cmd/oldlink/internal/ld/outbuf.go
deleted file mode 100644
index 596d239..0000000
--- a/src/cmd/oldlink/internal/ld/outbuf.go
+++ /dev/null
@@ -1,177 +0,0 @@
-// Copyright 2017 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 (
-	"bufio"
-	"cmd/internal/sys"
-	"cmd/oldlink/internal/sym"
-	"encoding/binary"
-	"log"
-	"os"
-)
-
-// OutBuf is a buffered file writer.
-//
-// It is simlar to the Writer in cmd/internal/bio with a few small differences.
-//
-// First, it tracks the output architecture and uses it to provide
-// endian helpers.
-//
-// Second, it provides a very cheap offset counter that doesn't require
-// any system calls to read the value.
-//
-// It also mmaps the output file (if available). The intended usage is:
-// - Mmap the output file
-// - Write the content
-// - possibly apply any edits in the output buffer
-// - Munmap the output file
-// - possibly write more content to the file, which will not be edited later.
-type OutBuf struct {
-	arch   *sys.Arch
-	off    int64
-	w      *bufio.Writer
-	buf    []byte // backing store of mmap'd output file
-	f      *os.File
-	encbuf [8]byte // temp buffer used by WriteN methods
-}
-
-func (out *OutBuf) SeekSet(p int64) {
-	if p == out.off {
-		return
-	}
-	if out.buf == nil {
-		out.Flush()
-		if _, err := out.f.Seek(p, 0); err != nil {
-			Exitf("seeking to %d in %s: %v", p, out.f.Name(), err)
-		}
-	}
-	out.off = p
-}
-
-func (out *OutBuf) Offset() int64 {
-	return out.off
-}
-
-// Write writes the contents of v to the buffer.
-//
-// As Write is backed by a bufio.Writer, callers do not have
-// to explicitly handle the returned error as long as Flush is
-// eventually called.
-func (out *OutBuf) Write(v []byte) (int, error) {
-	if out.buf != nil {
-		n := copy(out.buf[out.off:], v)
-		out.off += int64(n)
-		return n, nil
-	}
-	n, err := out.w.Write(v)
-	out.off += int64(n)
-	return n, err
-}
-
-func (out *OutBuf) Write8(v uint8) {
-	if out.buf != nil {
-		out.buf[out.off] = v
-		out.off++
-		return
-	}
-	if err := out.w.WriteByte(v); err == nil {
-		out.off++
-	}
-}
-
-// WriteByte is an alias for Write8 to fulfill the io.ByteWriter interface.
-func (out *OutBuf) WriteByte(v byte) error {
-	out.Write8(v)
-	return nil
-}
-
-func (out *OutBuf) Write16(v uint16) {
-	out.arch.ByteOrder.PutUint16(out.encbuf[:], v)
-	out.Write(out.encbuf[:2])
-}
-
-func (out *OutBuf) Write32(v uint32) {
-	out.arch.ByteOrder.PutUint32(out.encbuf[:], v)
-	out.Write(out.encbuf[:4])
-}
-
-func (out *OutBuf) Write32b(v uint32) {
-	binary.BigEndian.PutUint32(out.encbuf[:], v)
-	out.Write(out.encbuf[:4])
-}
-
-func (out *OutBuf) Write64(v uint64) {
-	out.arch.ByteOrder.PutUint64(out.encbuf[:], v)
-	out.Write(out.encbuf[:8])
-}
-
-func (out *OutBuf) Write64b(v uint64) {
-	binary.BigEndian.PutUint64(out.encbuf[:], v)
-	out.Write(out.encbuf[:8])
-}
-
-func (out *OutBuf) WriteString(s string) {
-	if out.buf != nil {
-		n := copy(out.buf[out.off:], s)
-		if n != len(s) {
-			log.Fatalf("WriteString truncated. buffer size: %d, offset: %d, len(s)=%d", len(out.buf), out.off, len(s))
-		}
-		out.off += int64(n)
-		return
-	}
-	n, _ := out.w.WriteString(s)
-	out.off += int64(n)
-}
-
-// WriteStringN writes the first n bytes of s.
-// If n is larger than len(s) then it is padded with zero bytes.
-func (out *OutBuf) WriteStringN(s string, n int) {
-	out.WriteStringPad(s, n, zeros[:])
-}
-
-// WriteStringPad writes the first n bytes of s.
-// If n is larger than len(s) then it is padded with the bytes in pad (repeated as needed).
-func (out *OutBuf) WriteStringPad(s string, n int, pad []byte) {
-	if len(s) >= n {
-		out.WriteString(s[:n])
-	} else {
-		out.WriteString(s)
-		n -= len(s)
-		for n > len(pad) {
-			out.Write(pad)
-			n -= len(pad)
-
-		}
-		out.Write(pad[:n])
-	}
-}
-
-// WriteSym writes the content of a Symbol, then changes the Symbol's content
-// to point to the output buffer that we just wrote, so we can apply further
-// edit to the symbol content.
-// If the output file is not Mmap'd, just writes the content.
-func (out *OutBuf) WriteSym(s *sym.Symbol) {
-	if out.buf != nil {
-		start := out.off
-		out.Write(s.P)
-		s.P = out.buf[start:out.off]
-		s.Attr.Set(sym.AttrReadOnly, false)
-	} else {
-		out.Write(s.P)
-	}
-}
-
-func (out *OutBuf) Flush() {
-	var err error
-	if out.buf != nil {
-		err = out.Msync()
-	} else {
-		err = out.w.Flush()
-	}
-	if err != nil {
-		Exitf("flushing %s: %v", out.f.Name(), err)
-	}
-}
diff --git a/src/cmd/oldlink/internal/ld/outbuf_mmap.go b/src/cmd/oldlink/internal/ld/outbuf_mmap.go
deleted file mode 100644
index 4075141..0000000
--- a/src/cmd/oldlink/internal/ld/outbuf_mmap.go
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright 2019 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.
-
-// +build darwin dragonfly freebsd linux openbsd
-
-package ld
-
-import (
-	"syscall"
-	"unsafe"
-)
-
-func (out *OutBuf) Mmap(filesize uint64) error {
-	err := out.f.Truncate(int64(filesize))
-	if err != nil {
-		Exitf("resize output file failed: %v", err)
-	}
-	out.buf, err = syscall.Mmap(int(out.f.Fd()), 0, int(filesize), syscall.PROT_READ|syscall.PROT_WRITE, syscall.MAP_SHARED|syscall.MAP_FILE)
-	return err
-}
-
-func (out *OutBuf) Munmap() {
-	err := out.Msync()
-	if err != nil {
-		Exitf("msync output file failed: %v", err)
-	}
-	syscall.Munmap(out.buf)
-	out.buf = nil
-	_, err = out.f.Seek(out.off, 0)
-	if err != nil {
-		Exitf("seek output file failed: %v", err)
-	}
-}
-
-func (out *OutBuf) Msync() error {
-	// TODO: netbsd supports mmap and msync, but the syscall package doesn't define MSYNC.
-	// It is excluded from the build tag for now.
-	_, _, errno := syscall.Syscall(syscall.SYS_MSYNC, uintptr(unsafe.Pointer(&out.buf[0])), uintptr(len(out.buf)), syscall.MS_SYNC)
-	if errno != 0 {
-		return errno
-	}
-	return nil
-}
diff --git a/src/cmd/oldlink/internal/ld/outbuf_nommap.go b/src/cmd/oldlink/internal/ld/outbuf_nommap.go
deleted file mode 100644
index fba8cd8..0000000
--- a/src/cmd/oldlink/internal/ld/outbuf_nommap.go
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright 2019 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.
-
-// +build !darwin,!dragonfly,!freebsd,!linux,!openbsd,!windows
-
-package ld
-
-import "errors"
-
-var errNotSupported = errors.New("mmap not supported")
-
-func (out *OutBuf) Mmap(filesize uint64) error { return errNotSupported }
-func (out *OutBuf) Munmap()                    { panic("unreachable") }
-func (out *OutBuf) Msync() error               { panic("unreachable") }
diff --git a/src/cmd/oldlink/internal/ld/outbuf_windows.go b/src/cmd/oldlink/internal/ld/outbuf_windows.go
deleted file mode 100644
index 1cb05c3..0000000
--- a/src/cmd/oldlink/internal/ld/outbuf_windows.go
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright 2019 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 (
-	"reflect"
-	"syscall"
-	"unsafe"
-)
-
-func (out *OutBuf) Mmap(filesize uint64) error {
-	err := out.f.Truncate(int64(filesize))
-	if err != nil {
-		Exitf("resize output file failed: %v", err)
-	}
-
-	low, high := uint32(filesize), uint32(filesize>>32)
-	fmap, err := syscall.CreateFileMapping(syscall.Handle(out.f.Fd()), nil, syscall.PAGE_READONLY, high, low, nil)
-	if err != nil {
-		return err
-	}
-	defer syscall.CloseHandle(fmap)
-
-	ptr, err := syscall.MapViewOfFile(fmap, syscall.FILE_MAP_READ|syscall.FILE_MAP_WRITE, 0, 0, uintptr(filesize))
-	if err != nil {
-		return err
-	}
-	*(*reflect.SliceHeader)(unsafe.Pointer(&out.buf)) = reflect.SliceHeader{Data: ptr, Len: int(filesize), Cap: int(filesize)}
-	return nil
-}
-
-func (out *OutBuf) Munmap() {
-	if out.buf == nil {
-		return
-	}
-	err := syscall.UnmapViewOfFile(uintptr(unsafe.Pointer(&out.buf[0])))
-	if err != nil {
-		Exitf("UnmapViewOfFile failed: %v", err)
-	}
-}
-
-func (out *OutBuf) Msync() error {
-	if out.buf == nil {
-		return nil
-	}
-	return syscall.FlushViewOfFile(uintptr(unsafe.Pointer(&out.buf[0])), 0)
-}
diff --git a/src/cmd/oldlink/internal/ld/pcln.go b/src/cmd/oldlink/internal/ld/pcln.go
deleted file mode 100644
index 7d53ab8..0000000
--- a/src/cmd/oldlink/internal/ld/pcln.go
+++ /dev/null
@@ -1,530 +0,0 @@
-// Copyright 2013 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/internal/objabi"
-	"cmd/internal/src"
-	"cmd/internal/sys"
-	"cmd/oldlink/internal/sym"
-	"encoding/binary"
-	"fmt"
-	"log"
-	"os"
-	"path/filepath"
-	"strings"
-)
-
-func ftabaddstring(ftab *sym.Symbol, s string) int32 {
-	start := len(ftab.P)
-	ftab.Grow(int64(start + len(s) + 1)) // make room for s plus trailing NUL
-	copy(ftab.P[start:], s)
-	return int32(start)
-}
-
-// numberfile assigns a file number to the file if it hasn't been assigned already.
-func numberfile(ctxt *Link, file *sym.Symbol) {
-	if file.Type != sym.SFILEPATH {
-		ctxt.Filesyms = append(ctxt.Filesyms, file)
-		file.Value = int64(len(ctxt.Filesyms))
-		file.Type = sym.SFILEPATH
-		path := file.Name[len(src.FileSymPrefix):]
-		file.Name = expandGoroot(path)
-	}
-}
-
-func renumberfiles(ctxt *Link, files []*sym.Symbol, d *sym.Pcdata) {
-	// Give files numbers.
-	for _, f := range files {
-		numberfile(ctxt, f)
-	}
-
-	buf := make([]byte, binary.MaxVarintLen32)
-	newval := int32(-1)
-	var out sym.Pcdata
-	it := obj.NewPCIter(uint32(ctxt.Arch.MinLC))
-	for it.Init(d.P); !it.Done; it.Next() {
-		// value delta
-		oldval := it.Value
-
-		var val int32
-		if oldval == -1 {
-			val = -1
-		} else {
-			if oldval < 0 || oldval >= int32(len(files)) {
-				log.Fatalf("bad pcdata %d", oldval)
-			}
-			val = int32(files[oldval].Value)
-		}
-
-		dv := val - newval
-		newval = val
-
-		// value
-		n := binary.PutVarint(buf, int64(dv))
-		out.P = append(out.P, buf[:n]...)
-
-		// pc delta
-		pc := (it.NextPC - it.PC) / it.PCScale
-		n = binary.PutUvarint(buf, uint64(pc))
-		out.P = append(out.P, buf[:n]...)
-	}
-
-	// terminating value delta
-	// we want to write varint-encoded 0, which is just 0
-	out.P = append(out.P, 0)
-
-	*d = out
-}
-
-// onlycsymbol reports whether this is a symbol that is referenced by C code.
-func onlycsymbol(s *sym.Symbol) bool {
-	switch s.Name {
-	case "_cgo_topofstack", "__cgo_topofstack", "_cgo_panic", "crosscall2":
-		return true
-	}
-	if strings.HasPrefix(s.Name, "_cgoexp_") {
-		return true
-	}
-	return false
-}
-
-func emitPcln(ctxt *Link, s *sym.Symbol) bool {
-	if s == nil {
-		return true
-	}
-	if ctxt.BuildMode == BuildModePlugin && ctxt.HeadType == objabi.Hdarwin && onlycsymbol(s) {
-		return false
-	}
-	// We want to generate func table entries only for the "lowest level" symbols,
-	// not containers of subsymbols.
-	return !s.Attr.Container()
-}
-
-// pclntab initializes the pclntab symbol with
-// runtime function and file name information.
-
-var pclntabZpcln sym.FuncInfo
-
-// These variables are used to initialize runtime.firstmoduledata, see symtab.go:symtab.
-var pclntabNfunc int32
-var pclntabFiletabOffset int32
-var pclntabPclntabOffset int32
-var pclntabFirstFunc *sym.Symbol
-var pclntabLastFunc *sym.Symbol
-
-func (ctxt *Link) pclntab() {
-	funcdataBytes := int64(0)
-	ftab := ctxt.Syms.Lookup("runtime.pclntab", 0)
-	ftab.Type = sym.SPCLNTAB
-	ftab.Attr |= sym.AttrReachable
-
-	// See golang.org/s/go12symtab for the format. Briefly:
-	//	8-byte header
-	//	nfunc [thearch.ptrsize bytes]
-	//	function table, alternating PC and offset to func struct [each entry thearch.ptrsize bytes]
-	//	end PC [thearch.ptrsize bytes]
-	//	offset to file table [4 bytes]
-
-	// Find container symbols and mark them as such.
-	for _, s := range ctxt.Textp {
-		if s.Outer != nil {
-			s.Outer.Attr |= sym.AttrContainer
-		}
-	}
-
-	// Gather some basic stats and info.
-	var nfunc int32
-	prevSect := ctxt.Textp[0].Sect
-	for _, s := range ctxt.Textp {
-		if !emitPcln(ctxt, s) {
-			continue
-		}
-		nfunc++
-		if pclntabFirstFunc == nil {
-			pclntabFirstFunc = s
-		}
-		if s.Sect != prevSect {
-			// With multiple text sections, the external linker may insert functions
-			// between the sections, which are not known by Go. This leaves holes in
-			// the PC range covered by the func table. We need to generate an entry
-			// to mark the hole.
-			nfunc++
-			prevSect = s.Sect
-		}
-	}
-
-	pclntabNfunc = nfunc
-	ftab.Grow(8 + int64(ctxt.Arch.PtrSize) + int64(nfunc)*2*int64(ctxt.Arch.PtrSize) + int64(ctxt.Arch.PtrSize) + 4)
-	ftab.SetUint32(ctxt.Arch, 0, 0xfffffffb)
-	ftab.SetUint8(ctxt.Arch, 6, uint8(ctxt.Arch.MinLC))
-	ftab.SetUint8(ctxt.Arch, 7, uint8(ctxt.Arch.PtrSize))
-	ftab.SetUint(ctxt.Arch, 8, uint64(nfunc))
-	pclntabPclntabOffset = int32(8 + ctxt.Arch.PtrSize)
-
-	funcnameoff := make(map[string]int32)
-	nameToOffset := func(name string) int32 {
-		nameoff, ok := funcnameoff[name]
-		if !ok {
-			nameoff = ftabaddstring(ftab, name)
-			funcnameoff[name] = nameoff
-		}
-		return nameoff
-	}
-
-	pctaboff := make(map[string]uint32)
-	writepctab := func(off int32, p []byte) int32 {
-		start, ok := pctaboff[string(p)]
-		if !ok {
-			if len(p) > 0 {
-				start = uint32(len(ftab.P))
-				ftab.AddBytes(p)
-			}
-			pctaboff[string(p)] = start
-		}
-		newoff := int32(ftab.SetUint32(ctxt.Arch, int64(off), start))
-		return newoff
-	}
-
-	nfunc = 0 // repurpose nfunc as a running index
-	prevFunc := ctxt.Textp[0]
-	for _, s := range ctxt.Textp {
-		if !emitPcln(ctxt, s) {
-			continue
-		}
-
-		if s.Sect != prevFunc.Sect {
-			// With multiple text sections, there may be a hole here in the address
-			// space (see the comment above). We use an invalid funcoff value to
-			// mark the hole.
-			// See also runtime/symtab.go:findfunc
-			ftab.SetAddrPlus(ctxt.Arch, 8+int64(ctxt.Arch.PtrSize)+int64(nfunc)*2*int64(ctxt.Arch.PtrSize), prevFunc, prevFunc.Size)
-			ftab.SetUint(ctxt.Arch, 8+int64(ctxt.Arch.PtrSize)+int64(nfunc)*2*int64(ctxt.Arch.PtrSize)+int64(ctxt.Arch.PtrSize), ^uint64(0))
-			nfunc++
-		}
-		prevFunc = s
-
-		pcln := s.FuncInfo
-		if pcln == nil {
-			pcln = &pclntabZpcln
-		}
-
-		if len(pcln.InlTree) > 0 {
-			if len(pcln.Pcdata) <= objabi.PCDATA_InlTreeIndex {
-				// Create inlining pcdata table.
-				pcdata := make([]sym.Pcdata, objabi.PCDATA_InlTreeIndex+1)
-				copy(pcdata, pcln.Pcdata)
-				pcln.Pcdata = pcdata
-			}
-
-			if len(pcln.Funcdataoff) <= objabi.FUNCDATA_InlTree {
-				// Create inline tree funcdata.
-				funcdata := make([]*sym.Symbol, objabi.FUNCDATA_InlTree+1)
-				funcdataoff := make([]int64, objabi.FUNCDATA_InlTree+1)
-				copy(funcdata, pcln.Funcdata)
-				copy(funcdataoff, pcln.Funcdataoff)
-				pcln.Funcdata = funcdata
-				pcln.Funcdataoff = funcdataoff
-			}
-		}
-
-		funcstart := int32(len(ftab.P))
-		funcstart += int32(-len(ftab.P)) & (int32(ctxt.Arch.PtrSize) - 1) // align to ptrsize
-
-		ftab.SetAddr(ctxt.Arch, 8+int64(ctxt.Arch.PtrSize)+int64(nfunc)*2*int64(ctxt.Arch.PtrSize), s)
-		ftab.SetUint(ctxt.Arch, 8+int64(ctxt.Arch.PtrSize)+int64(nfunc)*2*int64(ctxt.Arch.PtrSize)+int64(ctxt.Arch.PtrSize), uint64(funcstart))
-
-		// Write runtime._func. Keep in sync with ../../../../runtime/runtime2.go:/_func
-		// and package debug/gosym.
-
-		// fixed size of struct, checked below
-		off := funcstart
-
-		end := funcstart + int32(ctxt.Arch.PtrSize) + 3*4 + 5*4 + int32(len(pcln.Pcdata))*4 + int32(len(pcln.Funcdata))*int32(ctxt.Arch.PtrSize)
-		if len(pcln.Funcdata) > 0 && (end&int32(ctxt.Arch.PtrSize-1) != 0) {
-			end += 4
-		}
-		ftab.Grow(int64(end))
-
-		// entry uintptr
-		off = int32(ftab.SetAddr(ctxt.Arch, int64(off), s))
-
-		// name int32
-		nameoff := nameToOffset(s.Name)
-		off = int32(ftab.SetUint32(ctxt.Arch, int64(off), uint32(nameoff)))
-
-		// args int32
-		// TODO: Move into funcinfo.
-		args := uint32(0)
-		if s.FuncInfo != nil {
-			args = uint32(s.FuncInfo.Args)
-		}
-		off = int32(ftab.SetUint32(ctxt.Arch, int64(off), args))
-
-		// deferreturn
-		deferreturn := uint32(0)
-		lastWasmAddr := uint32(0)
-		for _, r := range s.R {
-			if ctxt.Arch.Family == sys.Wasm && r.Type == objabi.R_ADDR {
-				// Wasm does not have a live variable set at the deferreturn
-				// call itself. Instead it has one identified by the
-				// resumption point immediately preceding the deferreturn.
-				// The wasm code has a R_ADDR relocation which is used to
-				// set the resumption point to PC_B.
-				lastWasmAddr = uint32(r.Add)
-			}
-			if r.Type.IsDirectCall() && r.Sym != nil && r.Sym.Name == "runtime.deferreturn" {
-				if ctxt.Arch.Family == sys.Wasm {
-					deferreturn = lastWasmAddr - 1
-				} else {
-					// Note: the relocation target is in the call instruction, but
-					// is not necessarily the whole instruction (for instance, on
-					// x86 the relocation applies to bytes [1:5] of the 5 byte call
-					// instruction).
-					deferreturn = uint32(r.Off)
-					switch ctxt.Arch.Family {
-					case sys.AMD64, sys.I386:
-						deferreturn--
-					case sys.PPC64, sys.ARM, sys.ARM64, sys.MIPS, sys.MIPS64:
-						// no change
-					case sys.RISCV64:
-						// TODO(jsing): The JALR instruction is marked with
-						// R_CALLRISCV, whereas the actual reloc is currently
-						// one instruction earlier starting with the AUIPC.
-						deferreturn -= 4
-					case sys.S390X:
-						deferreturn -= 2
-					default:
-						panic(fmt.Sprint("Unhandled architecture:", ctxt.Arch.Family))
-					}
-				}
-				break // only need one
-			}
-		}
-		off = int32(ftab.SetUint32(ctxt.Arch, int64(off), deferreturn))
-
-		if pcln != &pclntabZpcln {
-			renumberfiles(ctxt, pcln.File, &pcln.Pcfile)
-			if false {
-				// Sanity check the new numbering
-				it := obj.NewPCIter(uint32(ctxt.Arch.MinLC))
-				for it.Init(pcln.Pcfile.P); !it.Done; it.Next() {
-					if it.Value < 1 || it.Value > int32(len(ctxt.Filesyms)) {
-						Errorf(s, "bad file number in pcfile: %d not in range [1, %d]\n", it.Value, len(ctxt.Filesyms))
-						errorexit()
-					}
-				}
-			}
-		}
-
-		if len(pcln.InlTree) > 0 {
-			inlTreeSym := ctxt.Syms.Lookup("inltree."+s.Name, 0)
-			inlTreeSym.Type = sym.SRODATA
-			inlTreeSym.Attr |= sym.AttrReachable | sym.AttrDuplicateOK
-
-			for i, call := range pcln.InlTree {
-				// Usually, call.File is already numbered since the file
-				// shows up in the Pcfile table. However, two inlined calls
-				// might overlap exactly so that only the innermost file
-				// appears in the Pcfile table. In that case, this assigns
-				// the outer file a number.
-				numberfile(ctxt, call.File)
-				nameoff := nameToOffset(call.Func)
-
-				inlTreeSym.SetUint16(ctxt.Arch, int64(i*20+0), uint16(call.Parent))
-				inlTreeSym.SetUint8(ctxt.Arch, int64(i*20+2), uint8(objabi.GetFuncID(call.Func, "")))
-				// byte 3 is unused
-				inlTreeSym.SetUint32(ctxt.Arch, int64(i*20+4), uint32(call.File.Value))
-				inlTreeSym.SetUint32(ctxt.Arch, int64(i*20+8), uint32(call.Line))
-				inlTreeSym.SetUint32(ctxt.Arch, int64(i*20+12), uint32(nameoff))
-				inlTreeSym.SetUint32(ctxt.Arch, int64(i*20+16), uint32(call.ParentPC))
-			}
-
-			pcln.Funcdata[objabi.FUNCDATA_InlTree] = inlTreeSym
-			pcln.Pcdata[objabi.PCDATA_InlTreeIndex] = pcln.Pcinline
-		}
-
-		// pcdata
-		off = writepctab(off, pcln.Pcsp.P)
-		off = writepctab(off, pcln.Pcfile.P)
-		off = writepctab(off, pcln.Pcline.P)
-		off = int32(ftab.SetUint32(ctxt.Arch, int64(off), uint32(len(pcln.Pcdata))))
-
-		// funcID uint8
-		var file string
-		if s.FuncInfo != nil && len(s.FuncInfo.File) > 0 {
-			file = s.FuncInfo.File[0].Name
-		}
-		funcID := objabi.GetFuncID(s.Name, file)
-
-		off = int32(ftab.SetUint8(ctxt.Arch, int64(off), uint8(funcID)))
-
-		// unused
-		off += 2
-
-		// nfuncdata must be the final entry.
-		off = int32(ftab.SetUint8(ctxt.Arch, int64(off), uint8(len(pcln.Funcdata))))
-		for i := range pcln.Pcdata {
-			off = writepctab(off, pcln.Pcdata[i].P)
-		}
-
-		// funcdata, must be pointer-aligned and we're only int32-aligned.
-		// Missing funcdata will be 0 (nil pointer).
-		if len(pcln.Funcdata) > 0 {
-			if off&int32(ctxt.Arch.PtrSize-1) != 0 {
-				off += 4
-			}
-			for i := range pcln.Funcdata {
-				dataoff := int64(off) + int64(ctxt.Arch.PtrSize)*int64(i)
-				if pcln.Funcdata[i] == nil {
-					ftab.SetUint(ctxt.Arch, dataoff, uint64(pcln.Funcdataoff[i]))
-					continue
-				}
-				// TODO: Dedup.
-				funcdataBytes += pcln.Funcdata[i].Size
-				ftab.SetAddrPlus(ctxt.Arch, dataoff, pcln.Funcdata[i], pcln.Funcdataoff[i])
-			}
-			off += int32(len(pcln.Funcdata)) * int32(ctxt.Arch.PtrSize)
-		}
-
-		if off != end {
-			Errorf(s, "bad math in functab: funcstart=%d off=%d but end=%d (npcdata=%d nfuncdata=%d ptrsize=%d)", funcstart, off, end, len(pcln.Pcdata), len(pcln.Funcdata), ctxt.Arch.PtrSize)
-			errorexit()
-		}
-
-		nfunc++
-	}
-
-	last := ctxt.Textp[len(ctxt.Textp)-1]
-	pclntabLastFunc = last
-	// Final entry of table is just end pc.
-	ftab.SetAddrPlus(ctxt.Arch, 8+int64(ctxt.Arch.PtrSize)+int64(nfunc)*2*int64(ctxt.Arch.PtrSize), last, last.Size)
-
-	// Start file table.
-	start := int32(len(ftab.P))
-
-	start += int32(-len(ftab.P)) & (int32(ctxt.Arch.PtrSize) - 1)
-	pclntabFiletabOffset = start
-	ftab.SetUint32(ctxt.Arch, 8+int64(ctxt.Arch.PtrSize)+int64(nfunc)*2*int64(ctxt.Arch.PtrSize)+int64(ctxt.Arch.PtrSize), uint32(start))
-
-	ftab.Grow(int64(start) + (int64(len(ctxt.Filesyms))+1)*4)
-	ftab.SetUint32(ctxt.Arch, int64(start), uint32(len(ctxt.Filesyms)+1))
-	for i := len(ctxt.Filesyms) - 1; i >= 0; i-- {
-		s := ctxt.Filesyms[i]
-		ftab.SetUint32(ctxt.Arch, int64(start)+s.Value*4, uint32(ftabaddstring(ftab, s.Name)))
-	}
-
-	ftab.Size = int64(len(ftab.P))
-
-	if ctxt.Debugvlog != 0 {
-		ctxt.Logf("pclntab=%d bytes, funcdata total %d bytes\n", ftab.Size, funcdataBytes)
-	}
-}
-
-func gorootFinal() string {
-	root := objabi.GOROOT
-	if final := os.Getenv("GOROOT_FINAL"); final != "" {
-		root = final
-	}
-	return root
-}
-
-func expandGoroot(s string) string {
-	const n = len("$GOROOT")
-	if len(s) >= n+1 && s[:n] == "$GOROOT" && (s[n] == '/' || s[n] == '\\') {
-		return filepath.ToSlash(filepath.Join(gorootFinal(), s[n:]))
-	}
-	return s
-}
-
-const (
-	BUCKETSIZE    = 256 * MINFUNC
-	SUBBUCKETS    = 16
-	SUBBUCKETSIZE = BUCKETSIZE / SUBBUCKETS
-	NOIDX         = 0x7fffffff
-)
-
-// findfunctab generates a lookup table to quickly find the containing
-// function for a pc. See src/runtime/symtab.go:findfunc for details.
-func (ctxt *Link) findfunctab() {
-	t := ctxt.Syms.Lookup("runtime.findfunctab", 0)
-	t.Type = sym.SRODATA
-	t.Attr |= sym.AttrReachable
-	t.Attr |= sym.AttrLocal
-
-	// find min and max address
-	min := ctxt.Textp[0].Value
-	lastp := ctxt.Textp[len(ctxt.Textp)-1]
-	max := lastp.Value + lastp.Size
-
-	// for each subbucket, compute the minimum of all symbol indexes
-	// that map to that subbucket.
-	n := int32((max - min + SUBBUCKETSIZE - 1) / SUBBUCKETSIZE)
-
-	indexes := make([]int32, n)
-	for i := int32(0); i < n; i++ {
-		indexes[i] = NOIDX
-	}
-	idx := int32(0)
-	for i, s := range ctxt.Textp {
-		if !emitPcln(ctxt, s) {
-			continue
-		}
-		p := s.Value
-		var e *sym.Symbol
-		i++
-		if i < len(ctxt.Textp) {
-			e = ctxt.Textp[i]
-		}
-		for !emitPcln(ctxt, e) && i < len(ctxt.Textp) {
-			e = ctxt.Textp[i]
-			i++
-		}
-		q := max
-		if e != nil {
-			q = e.Value
-		}
-
-		//print("%d: [%lld %lld] %s\n", idx, p, q, s->name);
-		for ; p < q; p += SUBBUCKETSIZE {
-			i = int((p - min) / SUBBUCKETSIZE)
-			if indexes[i] > idx {
-				indexes[i] = idx
-			}
-		}
-
-		i = int((q - 1 - min) / SUBBUCKETSIZE)
-		if indexes[i] > idx {
-			indexes[i] = idx
-		}
-		idx++
-	}
-
-	// allocate table
-	nbuckets := int32((max - min + BUCKETSIZE - 1) / BUCKETSIZE)
-
-	t.Grow(4*int64(nbuckets) + int64(n))
-
-	// fill in table
-	for i := int32(0); i < nbuckets; i++ {
-		base := indexes[i*SUBBUCKETS]
-		if base == NOIDX {
-			Errorf(nil, "hole in findfunctab")
-		}
-		t.SetUint32(ctxt.Arch, int64(i)*(4+SUBBUCKETS), uint32(base))
-		for j := int32(0); j < SUBBUCKETS && i*SUBBUCKETS+j < n; j++ {
-			idx = indexes[i*SUBBUCKETS+j]
-			if idx == NOIDX {
-				Errorf(nil, "hole in findfunctab")
-			}
-			if idx-base >= 256 {
-				Errorf(nil, "too many functions in a findfunc bucket! %d/%d %d %d", i, nbuckets, j, idx-base)
-			}
-
-			t.SetUint8(ctxt.Arch, int64(i)*(4+SUBBUCKETS)+4+int64(j), uint8(idx-base))
-		}
-	}
-}
diff --git a/src/cmd/oldlink/internal/ld/pe.go b/src/cmd/oldlink/internal/ld/pe.go
deleted file mode 100644
index b40557f..0000000
--- a/src/cmd/oldlink/internal/ld/pe.go
+++ /dev/null
@@ -1,1562 +0,0 @@
-// Copyright 2009 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.
-
-// PE (Portable Executable) file writing
-// https://www.microsoft.com/whdc/system/platform/firmware/PECOFF.mspx
-
-package ld
-
-import (
-	"cmd/internal/objabi"
-	"cmd/internal/sys"
-	"cmd/oldlink/internal/sym"
-	"debug/pe"
-	"encoding/binary"
-	"fmt"
-	"sort"
-	"strconv"
-	"strings"
-)
-
-type IMAGE_IMPORT_DESCRIPTOR struct {
-	OriginalFirstThunk uint32
-	TimeDateStamp      uint32
-	ForwarderChain     uint32
-	Name               uint32
-	FirstThunk         uint32
-}
-
-type IMAGE_EXPORT_DIRECTORY struct {
-	Characteristics       uint32
-	TimeDateStamp         uint32
-	MajorVersion          uint16
-	MinorVersion          uint16
-	Name                  uint32
-	Base                  uint32
-	NumberOfFunctions     uint32
-	NumberOfNames         uint32
-	AddressOfFunctions    uint32
-	AddressOfNames        uint32
-	AddressOfNameOrdinals uint32
-}
-
-const (
-	PEBASE = 0x00400000
-)
-
-var (
-	// SectionAlignment must be greater than or equal to FileAlignment.
-	// The default is the page size for the architecture.
-	PESECTALIGN int64 = 0x1000
-
-	// FileAlignment should be a power of 2 between 512 and 64 K, inclusive.
-	// The default is 512. If the SectionAlignment is less than
-	// the architecture's page size, then FileAlignment must match SectionAlignment.
-	PEFILEALIGN int64 = 2 << 8
-)
-
-const (
-	IMAGE_SCN_CNT_CODE               = 0x00000020
-	IMAGE_SCN_CNT_INITIALIZED_DATA   = 0x00000040
-	IMAGE_SCN_CNT_UNINITIALIZED_DATA = 0x00000080
-	IMAGE_SCN_MEM_EXECUTE            = 0x20000000
-	IMAGE_SCN_MEM_READ               = 0x40000000
-	IMAGE_SCN_MEM_WRITE              = 0x80000000
-	IMAGE_SCN_MEM_DISCARDABLE        = 0x2000000
-	IMAGE_SCN_LNK_NRELOC_OVFL        = 0x1000000
-	IMAGE_SCN_ALIGN_32BYTES          = 0x600000
-)
-
-// TODO(crawshaw): add these constants to debug/pe.
-const (
-	// TODO: the Microsoft doco says IMAGE_SYM_DTYPE_ARRAY is 3 and IMAGE_SYM_DTYPE_FUNCTION is 2
-	IMAGE_SYM_TYPE_NULL      = 0
-	IMAGE_SYM_TYPE_STRUCT    = 8
-	IMAGE_SYM_DTYPE_FUNCTION = 0x20
-	IMAGE_SYM_DTYPE_ARRAY    = 0x30
-	IMAGE_SYM_CLASS_EXTERNAL = 2
-	IMAGE_SYM_CLASS_STATIC   = 3
-
-	IMAGE_REL_I386_DIR32  = 0x0006
-	IMAGE_REL_I386_SECREL = 0x000B
-	IMAGE_REL_I386_REL32  = 0x0014
-
-	IMAGE_REL_AMD64_ADDR64 = 0x0001
-	IMAGE_REL_AMD64_ADDR32 = 0x0002
-	IMAGE_REL_AMD64_REL32  = 0x0004
-	IMAGE_REL_AMD64_SECREL = 0x000B
-
-	IMAGE_REL_ARM_ABSOLUTE = 0x0000
-	IMAGE_REL_ARM_ADDR32   = 0x0001
-	IMAGE_REL_ARM_ADDR32NB = 0x0002
-	IMAGE_REL_ARM_BRANCH24 = 0x0003
-	IMAGE_REL_ARM_BRANCH11 = 0x0004
-	IMAGE_REL_ARM_SECREL   = 0x000F
-
-	IMAGE_REL_BASED_HIGHLOW = 3
-	IMAGE_REL_BASED_DIR64   = 10
-)
-
-const (
-	PeMinimumTargetMajorVersion = 6
-	PeMinimumTargetMinorVersion = 1
-)
-
-// DOS stub that prints out
-// "This program cannot be run in DOS mode."
-var dosstub = []uint8{
-	0x4d,
-	0x5a,
-	0x90,
-	0x00,
-	0x03,
-	0x00,
-	0x04,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0xff,
-	0xff,
-	0x00,
-	0x00,
-	0x8b,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x40,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x80,
-	0x00,
-	0x00,
-	0x00,
-	0x0e,
-	0x1f,
-	0xba,
-	0x0e,
-	0x00,
-	0xb4,
-	0x09,
-	0xcd,
-	0x21,
-	0xb8,
-	0x01,
-	0x4c,
-	0xcd,
-	0x21,
-	0x54,
-	0x68,
-	0x69,
-	0x73,
-	0x20,
-	0x70,
-	0x72,
-	0x6f,
-	0x67,
-	0x72,
-	0x61,
-	0x6d,
-	0x20,
-	0x63,
-	0x61,
-	0x6e,
-	0x6e,
-	0x6f,
-	0x74,
-	0x20,
-	0x62,
-	0x65,
-	0x20,
-	0x72,
-	0x75,
-	0x6e,
-	0x20,
-	0x69,
-	0x6e,
-	0x20,
-	0x44,
-	0x4f,
-	0x53,
-	0x20,
-	0x6d,
-	0x6f,
-	0x64,
-	0x65,
-	0x2e,
-	0x0d,
-	0x0d,
-	0x0a,
-	0x24,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-}
-
-type Imp struct {
-	s       *sym.Symbol
-	off     uint64
-	next    *Imp
-	argsize int
-}
-
-type Dll struct {
-	name     string
-	nameoff  uint64
-	thunkoff uint64
-	ms       *Imp
-	next     *Dll
-}
-
-var (
-	rsrcsym     *sym.Symbol
-	PESECTHEADR int32
-	PEFILEHEADR int32
-	pe64        int
-	dr          *Dll
-	dexport     [1024]*sym.Symbol
-	nexport     int
-)
-
-// peStringTable is a COFF string table.
-type peStringTable struct {
-	strings    []string
-	stringsLen int
-}
-
-// size returns size of string table t.
-func (t *peStringTable) size() int {
-	// string table starts with 4-byte length at the beginning
-	return t.stringsLen + 4
-}
-
-// add adds string str to string table t.
-func (t *peStringTable) add(str string) int {
-	off := t.size()
-	t.strings = append(t.strings, str)
-	t.stringsLen += len(str) + 1 // each string will have 0 appended to it
-	return off
-}
-
-// write writes string table t into the output file.
-func (t *peStringTable) write(out *OutBuf) {
-	out.Write32(uint32(t.size()))
-	for _, s := range t.strings {
-		out.WriteString(s)
-		out.Write8(0)
-	}
-}
-
-// peSection represents section from COFF section table.
-type peSection struct {
-	name                 string
-	shortName            string
-	index                int // one-based index into the Section Table
-	virtualSize          uint32
-	virtualAddress       uint32
-	sizeOfRawData        uint32
-	pointerToRawData     uint32
-	pointerToRelocations uint32
-	numberOfRelocations  uint16
-	characteristics      uint32
-}
-
-// checkOffset verifies COFF section sect offset in the file.
-func (sect *peSection) checkOffset(off int64) {
-	if off != int64(sect.pointerToRawData) {
-		Errorf(nil, "%s.PointerToRawData = %#x, want %#x", sect.name, uint64(int64(sect.pointerToRawData)), uint64(off))
-		errorexit()
-	}
-}
-
-// checkSegment verifies COFF section sect matches address
-// and file offset provided in segment seg.
-func (sect *peSection) checkSegment(seg *sym.Segment) {
-	if seg.Vaddr-PEBASE != uint64(sect.virtualAddress) {
-		Errorf(nil, "%s.VirtualAddress = %#x, want %#x", sect.name, uint64(int64(sect.virtualAddress)), uint64(int64(seg.Vaddr-PEBASE)))
-		errorexit()
-	}
-	if seg.Fileoff != uint64(sect.pointerToRawData) {
-		Errorf(nil, "%s.PointerToRawData = %#x, want %#x", sect.name, uint64(int64(sect.pointerToRawData)), uint64(int64(seg.Fileoff)))
-		errorexit()
-	}
-}
-
-// pad adds zeros to the section sect. It writes as many bytes
-// as necessary to make section sect.SizeOfRawData bytes long.
-// It assumes that n bytes are already written to the file.
-func (sect *peSection) pad(out *OutBuf, n uint32) {
-	out.WriteStringN("", int(sect.sizeOfRawData-n))
-}
-
-// write writes COFF section sect into the output file.
-func (sect *peSection) write(out *OutBuf, linkmode LinkMode) error {
-	h := pe.SectionHeader32{
-		VirtualSize:          sect.virtualSize,
-		SizeOfRawData:        sect.sizeOfRawData,
-		PointerToRawData:     sect.pointerToRawData,
-		PointerToRelocations: sect.pointerToRelocations,
-		NumberOfRelocations:  sect.numberOfRelocations,
-		Characteristics:      sect.characteristics,
-	}
-	if linkmode != LinkExternal {
-		h.VirtualAddress = sect.virtualAddress
-	}
-	copy(h.Name[:], sect.shortName)
-	return binary.Write(out, binary.LittleEndian, h)
-}
-
-// emitRelocations emits the relocation entries for the sect.
-// The actual relocations are emitted by relocfn.
-// This updates the corresponding PE section table entry
-// with the relocation offset and count.
-func (sect *peSection) emitRelocations(out *OutBuf, relocfn func() int) {
-	sect.pointerToRelocations = uint32(out.Offset())
-	// first entry: extended relocs
-	out.Write32(0) // placeholder for number of relocation + 1
-	out.Write32(0)
-	out.Write16(0)
-
-	n := relocfn() + 1
-
-	cpos := out.Offset()
-	out.SeekSet(int64(sect.pointerToRelocations))
-	out.Write32(uint32(n))
-	out.SeekSet(cpos)
-	if n > 0x10000 {
-		n = 0x10000
-		sect.characteristics |= IMAGE_SCN_LNK_NRELOC_OVFL
-	} else {
-		sect.pointerToRelocations += 10 // skip the extend reloc entry
-	}
-	sect.numberOfRelocations = uint16(n - 1)
-}
-
-// peFile is used to build COFF file.
-type peFile struct {
-	sections       []*peSection
-	stringTable    peStringTable
-	textSect       *peSection
-	rdataSect      *peSection
-	dataSect       *peSection
-	bssSect        *peSection
-	ctorsSect      *peSection
-	nextSectOffset uint32
-	nextFileOffset uint32
-	symtabOffset   int64 // offset to the start of symbol table
-	symbolCount    int   // number of symbol table records written
-	dataDirectory  [16]pe.DataDirectory
-}
-
-// addSection adds section to the COFF file f.
-func (f *peFile) addSection(name string, sectsize int, filesize int) *peSection {
-	sect := &peSection{
-		name:             name,
-		shortName:        name,
-		index:            len(f.sections) + 1,
-		virtualSize:      uint32(sectsize),
-		virtualAddress:   f.nextSectOffset,
-		pointerToRawData: f.nextFileOffset,
-	}
-	f.nextSectOffset = uint32(Rnd(int64(f.nextSectOffset)+int64(sectsize), PESECTALIGN))
-	if filesize > 0 {
-		sect.sizeOfRawData = uint32(Rnd(int64(filesize), PEFILEALIGN))
-		f.nextFileOffset += sect.sizeOfRawData
-	}
-	f.sections = append(f.sections, sect)
-	return sect
-}
-
-// addDWARFSection adds DWARF section to the COFF file f.
-// This function is similar to addSection, but DWARF section names are
-// longer than 8 characters, so they need to be stored in the string table.
-func (f *peFile) addDWARFSection(name string, size int) *peSection {
-	if size == 0 {
-		Exitf("DWARF section %q is empty", name)
-	}
-	// DWARF section names are longer than 8 characters.
-	// PE format requires such names to be stored in string table,
-	// and section names replaced with slash (/) followed by
-	// correspondent string table index.
-	// see http://www.microsoft.com/whdc/system/platform/firmware/PECOFFdwn.mspx
-	// for details
-	off := f.stringTable.add(name)
-	h := f.addSection(name, size, size)
-	h.shortName = fmt.Sprintf("/%d", off)
-	h.characteristics = IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_DISCARDABLE
-	return h
-}
-
-// addDWARF adds DWARF information to the COFF file f.
-func (f *peFile) addDWARF() {
-	if *FlagS { // disable symbol table
-		return
-	}
-	if *FlagW { // disable dwarf
-		return
-	}
-	for _, sect := range Segdwarf.Sections {
-		h := f.addDWARFSection(sect.Name, int(sect.Length))
-		fileoff := sect.Vaddr - Segdwarf.Vaddr + Segdwarf.Fileoff
-		if uint64(h.pointerToRawData) != fileoff {
-			Exitf("%s.PointerToRawData = %#x, want %#x", sect.Name, h.pointerToRawData, fileoff)
-		}
-	}
-}
-
-// addInitArray adds .ctors COFF section to the file f.
-func (f *peFile) addInitArray(ctxt *Link) *peSection {
-	// The size below was determined by the specification for array relocations,
-	// and by observing what GCC writes here. If the initarray section grows to
-	// contain more than one constructor entry, the size will need to be 8 * constructor_count.
-	// However, the entire Go runtime is initialized from just one function, so it is unlikely
-	// that this will need to grow in the future.
-	var size int
-	switch objabi.GOARCH {
-	default:
-		Exitf("peFile.addInitArray: unsupported GOARCH=%q\n", objabi.GOARCH)
-	case "386":
-		size = 4
-	case "amd64":
-		size = 8
-	case "arm":
-		size = 4
-	}
-	sect := f.addSection(".ctors", size, size)
-	sect.characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
-	sect.sizeOfRawData = uint32(size)
-	ctxt.Out.SeekSet(int64(sect.pointerToRawData))
-	sect.checkOffset(ctxt.Out.Offset())
-
-	init_entry := ctxt.Syms.Lookup(*flagEntrySymbol, 0)
-	addr := uint64(init_entry.Value) - init_entry.Sect.Vaddr
-	switch objabi.GOARCH {
-	case "386", "arm":
-		ctxt.Out.Write32(uint32(addr))
-	case "amd64":
-		ctxt.Out.Write64(addr)
-	}
-	return sect
-}
-
-// emitRelocations emits relocation entries for go.o in external linking.
-func (f *peFile) emitRelocations(ctxt *Link) {
-	for ctxt.Out.Offset()&7 != 0 {
-		ctxt.Out.Write8(0)
-	}
-
-	// relocsect relocates symbols from first in section sect, and returns
-	// the total number of relocations emitted.
-	relocsect := func(sect *sym.Section, syms []*sym.Symbol, base uint64) int {
-		// If main section has no bits, nothing to relocate.
-		if sect.Vaddr >= sect.Seg.Vaddr+sect.Seg.Filelen {
-			return 0
-		}
-		relocs := 0
-		sect.Reloff = uint64(ctxt.Out.Offset())
-		for i, s := range syms {
-			if !s.Attr.Reachable() {
-				continue
-			}
-			if uint64(s.Value) >= sect.Vaddr {
-				syms = syms[i:]
-				break
-			}
-		}
-		eaddr := int32(sect.Vaddr + sect.Length)
-		for _, sym := range syms {
-			if !sym.Attr.Reachable() {
-				continue
-			}
-			if sym.Value >= int64(eaddr) {
-				break
-			}
-			for ri := range sym.R {
-				r := &sym.R[ri]
-				if r.Done {
-					continue
-				}
-				if r.Xsym == nil {
-					Errorf(sym, "missing xsym in relocation")
-					continue
-				}
-				if r.Xsym.Dynid < 0 {
-					Errorf(sym, "reloc %d to non-coff symbol %s (outer=%s) %d", r.Type, r.Sym.Name, r.Xsym.Name, r.Sym.Type)
-				}
-				if !thearch.PEreloc1(ctxt.Arch, ctxt.Out, sym, r, int64(uint64(sym.Value+int64(r.Off))-base)) {
-					Errorf(sym, "unsupported obj reloc %d/%d to %s", r.Type, r.Siz, r.Sym.Name)
-				}
-				relocs++
-			}
-		}
-		sect.Rellen = uint64(ctxt.Out.Offset()) - sect.Reloff
-		return relocs
-	}
-
-	sects := []struct {
-		peSect *peSection
-		seg    *sym.Segment
-		syms   []*sym.Symbol
-	}{
-		{f.textSect, &Segtext, ctxt.Textp},
-		{f.rdataSect, &Segrodata, datap},
-		{f.dataSect, &Segdata, datap},
-	}
-	for _, s := range sects {
-		s.peSect.emitRelocations(ctxt.Out, func() int {
-			var n int
-			for _, sect := range s.seg.Sections {
-				n += relocsect(sect, s.syms, s.seg.Vaddr)
-			}
-			return n
-		})
-	}
-
-dwarfLoop:
-	for _, sect := range Segdwarf.Sections {
-		for _, pesect := range f.sections {
-			if sect.Name == pesect.name {
-				pesect.emitRelocations(ctxt.Out, func() int {
-					return relocsect(sect, dwarfp, sect.Vaddr)
-				})
-				continue dwarfLoop
-			}
-		}
-		Errorf(nil, "emitRelocations: could not find %q section", sect.Name)
-	}
-
-	f.ctorsSect.emitRelocations(ctxt.Out, func() int {
-		dottext := ctxt.Syms.Lookup(".text", 0)
-		ctxt.Out.Write32(0)
-		ctxt.Out.Write32(uint32(dottext.Dynid))
-		switch objabi.GOARCH {
-		default:
-			Errorf(dottext, "unknown architecture for PE: %q\n", objabi.GOARCH)
-		case "386":
-			ctxt.Out.Write16(IMAGE_REL_I386_DIR32)
-		case "amd64":
-			ctxt.Out.Write16(IMAGE_REL_AMD64_ADDR64)
-		case "arm":
-			ctxt.Out.Write16(IMAGE_REL_ARM_ADDR32)
-		}
-		return 1
-	})
-}
-
-// writeSymbol appends symbol s to file f symbol table.
-// It also sets s.Dynid to written symbol number.
-func (f *peFile) writeSymbol(out *OutBuf, s *sym.Symbol, value int64, sectidx int, typ uint16, class uint8) {
-	if len(s.Name) > 8 {
-		out.Write32(0)
-		out.Write32(uint32(f.stringTable.add(s.Name)))
-	} else {
-		out.WriteStringN(s.Name, 8)
-	}
-	out.Write32(uint32(value))
-	out.Write16(uint16(sectidx))
-	out.Write16(typ)
-	out.Write8(class)
-	out.Write8(0) // no aux entries
-
-	s.Dynid = int32(f.symbolCount)
-
-	f.symbolCount++
-}
-
-// mapToPESection searches peFile f for s symbol's location.
-// It returns PE section index, and offset within that section.
-func (f *peFile) mapToPESection(s *sym.Symbol, linkmode LinkMode) (pesectidx int, offset int64, err error) {
-	if s.Sect == nil {
-		return 0, 0, fmt.Errorf("could not map %s symbol with no section", s.Name)
-	}
-	if s.Sect.Seg == &Segtext {
-		return f.textSect.index, int64(uint64(s.Value) - Segtext.Vaddr), nil
-	}
-	if s.Sect.Seg == &Segrodata {
-		return f.rdataSect.index, int64(uint64(s.Value) - Segrodata.Vaddr), nil
-	}
-	if s.Sect.Seg != &Segdata {
-		return 0, 0, fmt.Errorf("could not map %s symbol with non .text or .rdata or .data section", s.Name)
-	}
-	v := uint64(s.Value) - Segdata.Vaddr
-	if linkmode != LinkExternal {
-		return f.dataSect.index, int64(v), nil
-	}
-	if s.Type == sym.SDATA {
-		return f.dataSect.index, int64(v), nil
-	}
-	// Note: although address of runtime.edata (type sym.SDATA) is at the start of .bss section
-	// it still belongs to the .data section, not the .bss section.
-	if v < Segdata.Filelen {
-		return f.dataSect.index, int64(v), nil
-	}
-	return f.bssSect.index, int64(v - Segdata.Filelen), nil
-}
-
-// writeSymbols writes all COFF symbol table records.
-func (f *peFile) writeSymbols(ctxt *Link) {
-
-	put := func(ctxt *Link, s *sym.Symbol, name string, type_ SymbolType, addr int64, gotype *sym.Symbol) {
-		if s == nil {
-			return
-		}
-		if s.Sect == nil && type_ != UndefinedSym {
-			return
-		}
-		switch type_ {
-		default:
-			return
-		case DataSym, BSSSym, TextSym, UndefinedSym:
-		}
-
-		// Only windows/386 requires underscore prefix on external symbols.
-		if ctxt.Arch.Family == sys.I386 &&
-			ctxt.LinkMode == LinkExternal &&
-			(s.Type == sym.SHOSTOBJ || s.Type == sym.SUNDEFEXT || s.Attr.CgoExport()) {
-			s.Name = "_" + s.Name
-		}
-
-		var typ uint16
-		if ctxt.LinkMode == LinkExternal {
-			typ = IMAGE_SYM_TYPE_NULL
-		} else {
-			// TODO: fix IMAGE_SYM_DTYPE_ARRAY value and use following expression, instead of 0x0308
-			typ = IMAGE_SYM_DTYPE_ARRAY<<8 + IMAGE_SYM_TYPE_STRUCT
-			typ = 0x0308 // "array of structs"
-		}
-		sect, value, err := f.mapToPESection(s, ctxt.LinkMode)
-		if err != nil {
-			if type_ == UndefinedSym {
-				typ = IMAGE_SYM_DTYPE_FUNCTION
-			} else {
-				Errorf(s, "addpesym: %v", err)
-			}
-		}
-		class := IMAGE_SYM_CLASS_EXTERNAL
-		if s.IsFileLocal() || s.Attr.VisibilityHidden() || s.Attr.Local() {
-			class = IMAGE_SYM_CLASS_STATIC
-		}
-		f.writeSymbol(ctxt.Out, s, value, sect, typ, uint8(class))
-	}
-
-	if ctxt.LinkMode == LinkExternal {
-		// Include section symbols as external, because
-		// .ctors and .debug_* section relocations refer to it.
-		for _, pesect := range f.sections {
-			sym := ctxt.Syms.Lookup(pesect.name, 0)
-			f.writeSymbol(ctxt.Out, sym, 0, pesect.index, IMAGE_SYM_TYPE_NULL, IMAGE_SYM_CLASS_STATIC)
-		}
-	}
-
-	genasmsym(ctxt, put)
-}
-
-// writeSymbolTableAndStringTable writes out symbol and string tables for peFile f.
-func (f *peFile) writeSymbolTableAndStringTable(ctxt *Link) {
-	f.symtabOffset = ctxt.Out.Offset()
-
-	// write COFF symbol table
-	if !*FlagS || ctxt.LinkMode == LinkExternal {
-		f.writeSymbols(ctxt)
-	}
-
-	// update COFF file header and section table
-	size := f.stringTable.size() + 18*f.symbolCount
-	var h *peSection
-	if ctxt.LinkMode != LinkExternal {
-		// We do not really need .symtab for go.o, and if we have one, ld
-		// will also include it in the exe, and that will confuse windows.
-		h = f.addSection(".symtab", size, size)
-		h.characteristics = IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_DISCARDABLE
-		h.checkOffset(f.symtabOffset)
-	}
-
-	// write COFF string table
-	f.stringTable.write(ctxt.Out)
-	if ctxt.LinkMode != LinkExternal {
-		h.pad(ctxt.Out, uint32(size))
-	}
-}
-
-// writeFileHeader writes COFF file header for peFile f.
-func (f *peFile) writeFileHeader(ctxt *Link) {
-	var fh pe.FileHeader
-
-	switch ctxt.Arch.Family {
-	default:
-		Exitf("unknown PE architecture: %v", ctxt.Arch.Family)
-	case sys.AMD64:
-		fh.Machine = pe.IMAGE_FILE_MACHINE_AMD64
-	case sys.I386:
-		fh.Machine = pe.IMAGE_FILE_MACHINE_I386
-	case sys.ARM:
-		fh.Machine = pe.IMAGE_FILE_MACHINE_ARMNT
-	}
-
-	fh.NumberOfSections = uint16(len(f.sections))
-
-	// Being able to produce identical output for identical input is
-	// much more beneficial than having build timestamp in the header.
-	fh.TimeDateStamp = 0
-
-	if ctxt.LinkMode == LinkExternal {
-		fh.Characteristics = pe.IMAGE_FILE_LINE_NUMS_STRIPPED
-	} else {
-		fh.Characteristics = pe.IMAGE_FILE_EXECUTABLE_IMAGE | pe.IMAGE_FILE_DEBUG_STRIPPED
-		switch ctxt.Arch.Family {
-		case sys.AMD64, sys.I386:
-			if ctxt.BuildMode != BuildModePIE {
-				fh.Characteristics |= pe.IMAGE_FILE_RELOCS_STRIPPED
-			}
-		}
-	}
-	if pe64 != 0 {
-		var oh64 pe.OptionalHeader64
-		fh.SizeOfOptionalHeader = uint16(binary.Size(&oh64))
-		fh.Characteristics |= pe.IMAGE_FILE_LARGE_ADDRESS_AWARE
-	} else {
-		var oh pe.OptionalHeader32
-		fh.SizeOfOptionalHeader = uint16(binary.Size(&oh))
-		fh.Characteristics |= pe.IMAGE_FILE_32BIT_MACHINE
-	}
-
-	fh.PointerToSymbolTable = uint32(f.symtabOffset)
-	fh.NumberOfSymbols = uint32(f.symbolCount)
-
-	binary.Write(ctxt.Out, binary.LittleEndian, &fh)
-}
-
-// writeOptionalHeader writes COFF optional header for peFile f.
-func (f *peFile) writeOptionalHeader(ctxt *Link) {
-	var oh pe.OptionalHeader32
-	var oh64 pe.OptionalHeader64
-
-	if pe64 != 0 {
-		oh64.Magic = 0x20b // PE32+
-	} else {
-		oh.Magic = 0x10b // PE32
-		oh.BaseOfData = f.dataSect.virtualAddress
-	}
-
-	// Fill out both oh64 and oh. We only use one. Oh well.
-	oh64.MajorLinkerVersion = 3
-	oh.MajorLinkerVersion = 3
-	oh64.MinorLinkerVersion = 0
-	oh.MinorLinkerVersion = 0
-	oh64.SizeOfCode = f.textSect.sizeOfRawData
-	oh.SizeOfCode = f.textSect.sizeOfRawData
-	oh64.SizeOfInitializedData = f.dataSect.sizeOfRawData
-	oh.SizeOfInitializedData = f.dataSect.sizeOfRawData
-	oh64.SizeOfUninitializedData = 0
-	oh.SizeOfUninitializedData = 0
-	if ctxt.LinkMode != LinkExternal {
-		oh64.AddressOfEntryPoint = uint32(Entryvalue(ctxt) - PEBASE)
-		oh.AddressOfEntryPoint = uint32(Entryvalue(ctxt) - PEBASE)
-	}
-	oh64.BaseOfCode = f.textSect.virtualAddress
-	oh.BaseOfCode = f.textSect.virtualAddress
-	oh64.ImageBase = PEBASE
-	oh.ImageBase = PEBASE
-	oh64.SectionAlignment = uint32(PESECTALIGN)
-	oh.SectionAlignment = uint32(PESECTALIGN)
-	oh64.FileAlignment = uint32(PEFILEALIGN)
-	oh.FileAlignment = uint32(PEFILEALIGN)
-	oh64.MajorOperatingSystemVersion = PeMinimumTargetMajorVersion
-	oh.MajorOperatingSystemVersion = PeMinimumTargetMajorVersion
-	oh64.MinorOperatingSystemVersion = PeMinimumTargetMinorVersion
-	oh.MinorOperatingSystemVersion = PeMinimumTargetMinorVersion
-	oh64.MajorImageVersion = 1
-	oh.MajorImageVersion = 1
-	oh64.MinorImageVersion = 0
-	oh.MinorImageVersion = 0
-	oh64.MajorSubsystemVersion = PeMinimumTargetMajorVersion
-	oh.MajorSubsystemVersion = PeMinimumTargetMajorVersion
-	oh64.MinorSubsystemVersion = PeMinimumTargetMinorVersion
-	oh.MinorSubsystemVersion = PeMinimumTargetMinorVersion
-	oh64.SizeOfImage = f.nextSectOffset
-	oh.SizeOfImage = f.nextSectOffset
-	oh64.SizeOfHeaders = uint32(PEFILEHEADR)
-	oh.SizeOfHeaders = uint32(PEFILEHEADR)
-	if windowsgui {
-		oh64.Subsystem = pe.IMAGE_SUBSYSTEM_WINDOWS_GUI
-		oh.Subsystem = pe.IMAGE_SUBSYSTEM_WINDOWS_GUI
-	} else {
-		oh64.Subsystem = pe.IMAGE_SUBSYSTEM_WINDOWS_CUI
-		oh.Subsystem = pe.IMAGE_SUBSYSTEM_WINDOWS_CUI
-	}
-
-	// Mark as having awareness of terminal services, to avoid ancient compatibility hacks.
-	oh64.DllCharacteristics |= pe.IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE
-	oh.DllCharacteristics |= pe.IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE
-
-	// Enable DEP
-	oh64.DllCharacteristics |= pe.IMAGE_DLLCHARACTERISTICS_NX_COMPAT
-	oh.DllCharacteristics |= pe.IMAGE_DLLCHARACTERISTICS_NX_COMPAT
-
-	// The DLL can be relocated at load time.
-	switch ctxt.Arch.Family {
-	case sys.AMD64, sys.I386:
-		if ctxt.BuildMode == BuildModePIE {
-			oh64.DllCharacteristics |= pe.IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE
-			oh.DllCharacteristics |= pe.IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE
-		}
-	case sys.ARM:
-		oh64.DllCharacteristics |= pe.IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE
-		oh.DllCharacteristics |= pe.IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE
-	}
-
-	// Image can handle a high entropy 64-bit virtual address space.
-	if ctxt.BuildMode == BuildModePIE {
-		oh64.DllCharacteristics |= pe.IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA
-	}
-
-	// Disable stack growth as we don't want Windows to
-	// fiddle with the thread stack limits, which we set
-	// ourselves to circumvent the stack checks in the
-	// Windows exception dispatcher.
-	// Commit size must be strictly less than reserve
-	// size otherwise reserve will be rounded up to a
-	// larger size, as verified with VMMap.
-
-	// On 64-bit, we always reserve 2MB stacks. "Pure" Go code is
-	// okay with much smaller stacks, but the syscall package
-	// makes it easy to call into arbitrary C code without cgo,
-	// and system calls even in "pure" Go code are actually C
-	// calls that may need more stack than we think.
-	//
-	// The default stack reserve size directly affects only the main
-	// thread, ctrlhandler thread, and profileloop thread. For
-	// these, it must be greater than the stack size assumed by
-	// externalthreadhandler.
-	//
-	// For other threads, the runtime explicitly asks the kernel
-	// to use the default stack size so that all stacks are
-	// consistent.
-	//
-	// At thread start, in minit, the runtime queries the OS for
-	// the actual stack bounds so that the stack size doesn't need
-	// to be hard-coded into the runtime.
-	oh64.SizeOfStackReserve = 0x00200000
-	if !iscgo {
-		oh64.SizeOfStackCommit = 0x00001000
-	} else {
-		// TODO(brainman): Maybe remove optional header writing altogether for cgo.
-		// For cgo it is the external linker that is building final executable.
-		// And it probably does not use any information stored in optional header.
-		oh64.SizeOfStackCommit = 0x00200000 - 0x2000 // account for 2 guard pages
-	}
-
-	oh.SizeOfStackReserve = 0x00100000
-	if !iscgo {
-		oh.SizeOfStackCommit = 0x00001000
-	} else {
-		oh.SizeOfStackCommit = 0x00100000 - 0x2000 // account for 2 guard pages
-	}
-
-	oh64.SizeOfHeapReserve = 0x00100000
-	oh.SizeOfHeapReserve = 0x00100000
-	oh64.SizeOfHeapCommit = 0x00001000
-	oh.SizeOfHeapCommit = 0x00001000
-	oh64.NumberOfRvaAndSizes = 16
-	oh.NumberOfRvaAndSizes = 16
-
-	if pe64 != 0 {
-		oh64.DataDirectory = f.dataDirectory
-	} else {
-		oh.DataDirectory = f.dataDirectory
-	}
-
-	if pe64 != 0 {
-		binary.Write(ctxt.Out, binary.LittleEndian, &oh64)
-	} else {
-		binary.Write(ctxt.Out, binary.LittleEndian, &oh)
-	}
-}
-
-var pefile peFile
-
-func Peinit(ctxt *Link) {
-	var l int
-
-	switch ctxt.Arch.Family {
-	// 64-bit architectures
-	case sys.AMD64:
-		pe64 = 1
-		var oh64 pe.OptionalHeader64
-		l = binary.Size(&oh64)
-
-	// 32-bit architectures
-	default:
-		var oh pe.OptionalHeader32
-		l = binary.Size(&oh)
-
-	}
-
-	if ctxt.LinkMode == LinkExternal {
-		// .rdata section will contain "masks" and "shifts" symbols, and they
-		// need to be aligned to 16-bytes. So make all sections aligned
-		// to 32-byte and mark them all IMAGE_SCN_ALIGN_32BYTES so external
-		// linker will honour that requirement.
-		PESECTALIGN = 32
-		PEFILEALIGN = 0
-	}
-
-	var sh [16]pe.SectionHeader32
-	var fh pe.FileHeader
-	PEFILEHEADR = int32(Rnd(int64(len(dosstub)+binary.Size(&fh)+l+binary.Size(&sh)), PEFILEALIGN))
-	if ctxt.LinkMode != LinkExternal {
-		PESECTHEADR = int32(Rnd(int64(PEFILEHEADR), PESECTALIGN))
-	} else {
-		PESECTHEADR = 0
-	}
-	pefile.nextSectOffset = uint32(PESECTHEADR)
-	pefile.nextFileOffset = uint32(PEFILEHEADR)
-
-	if ctxt.LinkMode == LinkInternal {
-		// some mingw libs depend on this symbol, for example, FindPESectionByName
-		ctxt.xdefine("__image_base__", sym.SDATA, PEBASE)
-		ctxt.xdefine("_image_base__", sym.SDATA, PEBASE)
-	}
-
-	HEADR = PEFILEHEADR
-	if *FlagTextAddr == -1 {
-		*FlagTextAddr = PEBASE + int64(PESECTHEADR)
-	}
-	if *FlagRound == -1 {
-		*FlagRound = int(PESECTALIGN)
-	}
-}
-
-func pewrite(ctxt *Link) {
-	ctxt.Out.SeekSet(0)
-	if ctxt.LinkMode != LinkExternal {
-		ctxt.Out.Write(dosstub)
-		ctxt.Out.WriteStringN("PE", 4)
-	}
-
-	pefile.writeFileHeader(ctxt)
-
-	pefile.writeOptionalHeader(ctxt)
-
-	for _, sect := range pefile.sections {
-		sect.write(ctxt.Out, ctxt.LinkMode)
-	}
-}
-
-func strput(out *OutBuf, s string) {
-	out.WriteString(s)
-	out.Write8(0)
-	// string must be padded to even size
-	if (len(s)+1)%2 != 0 {
-		out.Write8(0)
-	}
-}
-
-func initdynimport(ctxt *Link) *Dll {
-	var d *Dll
-
-	dr = nil
-	var m *Imp
-	for _, s := range ctxt.Syms.Allsym {
-		if !s.Attr.Reachable() || s.Type != sym.SDYNIMPORT {
-			continue
-		}
-		for d = dr; d != nil; d = d.next {
-			if d.name == s.Dynimplib() {
-				m = new(Imp)
-				break
-			}
-		}
-
-		if d == nil {
-			d = new(Dll)
-			d.name = s.Dynimplib()
-			d.next = dr
-			dr = d
-			m = new(Imp)
-		}
-
-		// Because external link requires properly stdcall decorated name,
-		// all external symbols in runtime use %n to denote that the number
-		// of uinptrs this function consumes. Store the argsize and discard
-		// the %n suffix if any.
-		m.argsize = -1
-		extName := s.Extname()
-		if i := strings.IndexByte(extName, '%'); i >= 0 {
-			var err error
-			m.argsize, err = strconv.Atoi(extName[i+1:])
-			if err != nil {
-				Errorf(s, "failed to parse stdcall decoration: %v", err)
-			}
-			m.argsize *= ctxt.Arch.PtrSize
-			s.SetExtname(extName[:i])
-		}
-
-		m.s = s
-		m.next = d.ms
-		d.ms = m
-	}
-
-	if ctxt.LinkMode == LinkExternal {
-		// Add real symbol name
-		for d := dr; d != nil; d = d.next {
-			for m = d.ms; m != nil; m = m.next {
-				m.s.Type = sym.SDATA
-				m.s.Grow(int64(ctxt.Arch.PtrSize))
-				dynName := m.s.Extname()
-				// only windows/386 requires stdcall decoration
-				if ctxt.Arch.Family == sys.I386 && m.argsize >= 0 {
-					dynName += fmt.Sprintf("@%d", m.argsize)
-				}
-				dynSym := ctxt.Syms.Lookup(dynName, 0)
-				dynSym.Attr |= sym.AttrReachable
-				dynSym.Type = sym.SHOSTOBJ
-				r := m.s.AddRel()
-				r.Sym = dynSym
-				r.Off = 0
-				r.Siz = uint8(ctxt.Arch.PtrSize)
-				r.Type = objabi.R_ADDR
-			}
-		}
-	} else {
-		dynamic := ctxt.Syms.Lookup(".windynamic", 0)
-		dynamic.Attr |= sym.AttrReachable
-		dynamic.Type = sym.SWINDOWS
-		for d := dr; d != nil; d = d.next {
-			for m = d.ms; m != nil; m = m.next {
-				m.s.Type = sym.SWINDOWS
-				m.s.Attr |= sym.AttrSubSymbol
-				m.s.Sub = dynamic.Sub
-				dynamic.Sub = m.s
-				m.s.Value = dynamic.Size
-				dynamic.Size += int64(ctxt.Arch.PtrSize)
-			}
-
-			dynamic.Size += int64(ctxt.Arch.PtrSize)
-		}
-	}
-
-	return dr
-}
-
-// peimporteddlls returns the gcc command line argument to link all imported
-// DLLs.
-func peimporteddlls() []string {
-	var dlls []string
-
-	for d := dr; d != nil; d = d.next {
-		dlls = append(dlls, "-l"+strings.TrimSuffix(d.name, ".dll"))
-	}
-
-	return dlls
-}
-
-func addimports(ctxt *Link, datsect *peSection) {
-	startoff := ctxt.Out.Offset()
-	dynamic := ctxt.Syms.Lookup(".windynamic", 0)
-
-	// skip import descriptor table (will write it later)
-	n := uint64(0)
-
-	for d := dr; d != nil; d = d.next {
-		n++
-	}
-	ctxt.Out.SeekSet(startoff + int64(binary.Size(&IMAGE_IMPORT_DESCRIPTOR{}))*int64(n+1))
-
-	// write dll names
-	for d := dr; d != nil; d = d.next {
-		d.nameoff = uint64(ctxt.Out.Offset()) - uint64(startoff)
-		strput(ctxt.Out, d.name)
-	}
-
-	// write function names
-	for d := dr; d != nil; d = d.next {
-		for m := d.ms; m != nil; m = m.next {
-			m.off = uint64(pefile.nextSectOffset) + uint64(ctxt.Out.Offset()) - uint64(startoff)
-			ctxt.Out.Write16(0) // hint
-			strput(ctxt.Out, m.s.Extname())
-		}
-	}
-
-	// write OriginalFirstThunks
-	oftbase := uint64(ctxt.Out.Offset()) - uint64(startoff)
-
-	n = uint64(ctxt.Out.Offset())
-	for d := dr; d != nil; d = d.next {
-		d.thunkoff = uint64(ctxt.Out.Offset()) - n
-		for m := d.ms; m != nil; m = m.next {
-			if pe64 != 0 {
-				ctxt.Out.Write64(m.off)
-			} else {
-				ctxt.Out.Write32(uint32(m.off))
-			}
-		}
-
-		if pe64 != 0 {
-			ctxt.Out.Write64(0)
-		} else {
-			ctxt.Out.Write32(0)
-		}
-	}
-
-	// add pe section and pad it at the end
-	n = uint64(ctxt.Out.Offset()) - uint64(startoff)
-
-	isect := pefile.addSection(".idata", int(n), int(n))
-	isect.characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE
-	isect.checkOffset(startoff)
-	isect.pad(ctxt.Out, uint32(n))
-	endoff := ctxt.Out.Offset()
-
-	// write FirstThunks (allocated in .data section)
-	ftbase := uint64(dynamic.Value) - uint64(datsect.virtualAddress) - PEBASE
-
-	ctxt.Out.SeekSet(int64(uint64(datsect.pointerToRawData) + ftbase))
-	for d := dr; d != nil; d = d.next {
-		for m := d.ms; m != nil; m = m.next {
-			if pe64 != 0 {
-				ctxt.Out.Write64(m.off)
-			} else {
-				ctxt.Out.Write32(uint32(m.off))
-			}
-		}
-
-		if pe64 != 0 {
-			ctxt.Out.Write64(0)
-		} else {
-			ctxt.Out.Write32(0)
-		}
-	}
-
-	// finally write import descriptor table
-	out := ctxt.Out
-	out.SeekSet(startoff)
-
-	for d := dr; d != nil; d = d.next {
-		out.Write32(uint32(uint64(isect.virtualAddress) + oftbase + d.thunkoff))
-		out.Write32(0)
-		out.Write32(0)
-		out.Write32(uint32(uint64(isect.virtualAddress) + d.nameoff))
-		out.Write32(uint32(uint64(datsect.virtualAddress) + ftbase + d.thunkoff))
-	}
-
-	out.Write32(0) //end
-	out.Write32(0)
-	out.Write32(0)
-	out.Write32(0)
-	out.Write32(0)
-
-	// update data directory
-	pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress = isect.virtualAddress
-	pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_IMPORT].Size = isect.virtualSize
-	pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress = uint32(dynamic.Value - PEBASE)
-	pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_IAT].Size = uint32(dynamic.Size)
-
-	out.SeekSet(endoff)
-}
-
-type byExtname []*sym.Symbol
-
-func (s byExtname) Len() int           { return len(s) }
-func (s byExtname) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
-func (s byExtname) Less(i, j int) bool { return s[i].Extname() < s[j].Extname() }
-
-func initdynexport(ctxt *Link) {
-	nexport = 0
-	for _, s := range ctxt.Syms.Allsym {
-		if !s.Attr.Reachable() || !s.Attr.CgoExportDynamic() {
-			continue
-		}
-		if nexport+1 > len(dexport) {
-			Errorf(s, "pe dynexport table is full")
-			errorexit()
-		}
-
-		dexport[nexport] = s
-		nexport++
-	}
-
-	sort.Sort(byExtname(dexport[:nexport]))
-}
-
-func addexports(ctxt *Link) {
-	var e IMAGE_EXPORT_DIRECTORY
-
-	size := binary.Size(&e) + 10*nexport + len(*flagOutfile) + 1
-	for i := 0; i < nexport; i++ {
-		size += len(dexport[i].Extname()) + 1
-	}
-
-	if nexport == 0 {
-		return
-	}
-
-	sect := pefile.addSection(".edata", size, size)
-	sect.characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
-	sect.checkOffset(ctxt.Out.Offset())
-	va := int(sect.virtualAddress)
-	pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress = uint32(va)
-	pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_EXPORT].Size = sect.virtualSize
-
-	vaName := va + binary.Size(&e) + nexport*4
-	vaAddr := va + binary.Size(&e)
-	vaNa := va + binary.Size(&e) + nexport*8
-
-	e.Characteristics = 0
-	e.MajorVersion = 0
-	e.MinorVersion = 0
-	e.NumberOfFunctions = uint32(nexport)
-	e.NumberOfNames = uint32(nexport)
-	e.Name = uint32(va+binary.Size(&e)) + uint32(nexport)*10 // Program names.
-	e.Base = 1
-	e.AddressOfFunctions = uint32(vaAddr)
-	e.AddressOfNames = uint32(vaName)
-	e.AddressOfNameOrdinals = uint32(vaNa)
-
-	out := ctxt.Out
-
-	// put IMAGE_EXPORT_DIRECTORY
-	binary.Write(out, binary.LittleEndian, &e)
-
-	// put EXPORT Address Table
-	for i := 0; i < nexport; i++ {
-		out.Write32(uint32(dexport[i].Value - PEBASE))
-	}
-
-	// put EXPORT Name Pointer Table
-	v := int(e.Name + uint32(len(*flagOutfile)) + 1)
-
-	for i := 0; i < nexport; i++ {
-		out.Write32(uint32(v))
-		v += len(dexport[i].Extname()) + 1
-	}
-
-	// put EXPORT Ordinal Table
-	for i := 0; i < nexport; i++ {
-		out.Write16(uint16(i))
-	}
-
-	// put Names
-	out.WriteStringN(*flagOutfile, len(*flagOutfile)+1)
-
-	for i := 0; i < nexport; i++ {
-		out.WriteStringN(dexport[i].Extname(), len(dexport[i].Extname())+1)
-	}
-	sect.pad(out, uint32(size))
-}
-
-// peBaseRelocEntry represents a single relocation entry.
-type peBaseRelocEntry struct {
-	typeOff uint16
-	rel     *sym.Reloc
-	sym     *sym.Symbol // For debug
-}
-
-// peBaseRelocBlock represents a Base Relocation Block. A block
-// is a collection of relocation entries in a page, where each
-// entry describes a single relocation.
-// The block page RVA (Relative Virtual Address) is the index
-// into peBaseRelocTable.blocks.
-type peBaseRelocBlock struct {
-	entries []peBaseRelocEntry
-}
-
-// pePages is a type used to store the list of pages for which there
-// are base relocation blocks. This is defined as a type so that
-// it can be sorted.
-type pePages []uint32
-
-func (p pePages) Len() int           { return len(p) }
-func (p pePages) Swap(i, j int)      { p[i], p[j] = p[j], p[i] }
-func (p pePages) Less(i, j int) bool { return p[i] < p[j] }
-
-// A PE base relocation table is a list of blocks, where each block
-// contains relocation information for a single page. The blocks
-// must be emitted in order of page virtual address.
-// See https://docs.microsoft.com/en-us/windows/desktop/debug/pe-format#the-reloc-section-image-only
-type peBaseRelocTable struct {
-	blocks map[uint32]peBaseRelocBlock
-
-	// pePages is a list of keys into blocks map.
-	// It is stored separately for ease of sorting.
-	pages pePages
-}
-
-func (rt *peBaseRelocTable) init(ctxt *Link) {
-	rt.blocks = make(map[uint32]peBaseRelocBlock)
-}
-
-func (rt *peBaseRelocTable) addentry(ctxt *Link, s *sym.Symbol, r *sym.Reloc) {
-	// pageSize is the size in bytes of a page
-	// described by a base relocation block.
-	const pageSize = 0x1000
-	const pageMask = pageSize - 1
-
-	addr := s.Value + int64(r.Off) - int64(PEBASE)
-	page := uint32(addr &^ pageMask)
-	off := uint32(addr & pageMask)
-
-	b, ok := rt.blocks[page]
-	if !ok {
-		rt.pages = append(rt.pages, page)
-	}
-
-	e := peBaseRelocEntry{
-		typeOff: uint16(off & 0xFFF),
-		rel:     r,
-		sym:     s,
-	}
-
-	// Set entry type
-	switch r.Siz {
-	default:
-		Exitf("unsupported relocation size %d\n", r.Siz)
-	case 4:
-		e.typeOff |= uint16(IMAGE_REL_BASED_HIGHLOW << 12)
-	case 8:
-		e.typeOff |= uint16(IMAGE_REL_BASED_DIR64 << 12)
-	}
-
-	b.entries = append(b.entries, e)
-	rt.blocks[page] = b
-}
-
-func (rt *peBaseRelocTable) write(ctxt *Link) {
-	out := ctxt.Out
-
-	// sort the pages array
-	sort.Sort(rt.pages)
-
-	for _, p := range rt.pages {
-		b := rt.blocks[p]
-		const sizeOfPEbaseRelocBlock = 8 // 2 * sizeof(uint32)
-		blockSize := uint32(sizeOfPEbaseRelocBlock + len(b.entries)*2)
-		out.Write32(p)
-		out.Write32(blockSize)
-
-		for _, e := range b.entries {
-			out.Write16(e.typeOff)
-		}
-	}
-}
-
-func addPEBaseRelocSym(ctxt *Link, s *sym.Symbol, rt *peBaseRelocTable) {
-	for ri := 0; ri < len(s.R); ri++ {
-		r := &s.R[ri]
-
-		if r.Sym == nil {
-			continue
-		}
-		if !r.Sym.Attr.Reachable() {
-			continue
-		}
-		if r.Type >= objabi.ElfRelocOffset {
-			continue
-		}
-		if r.Siz == 0 { // informational relocation
-			continue
-		}
-		if r.Type == objabi.R_DWARFFILEREF {
-			continue
-		}
-
-		switch r.Type {
-		default:
-		case objabi.R_ADDR:
-			rt.addentry(ctxt, s, r)
-		}
-	}
-}
-
-func addPEBaseReloc(ctxt *Link) {
-	// Arm does not work without base relocation table.
-	// 386 and amd64 will only require the table for BuildModePIE.
-	switch ctxt.Arch.Family {
-	default:
-		return
-	case sys.I386, sys.AMD64:
-		if ctxt.BuildMode != BuildModePIE {
-			return
-		}
-	case sys.ARM:
-	}
-
-	var rt peBaseRelocTable
-	rt.init(ctxt)
-
-	// Get relocation information
-	for _, s := range ctxt.Textp {
-		addPEBaseRelocSym(ctxt, s, &rt)
-	}
-	for _, s := range datap {
-		addPEBaseRelocSym(ctxt, s, &rt)
-	}
-
-	// Write relocation information
-	startoff := ctxt.Out.Offset()
-	rt.write(ctxt)
-	size := ctxt.Out.Offset() - startoff
-
-	// Add a PE section and pad it at the end
-	rsect := pefile.addSection(".reloc", int(size), int(size))
-	rsect.characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_DISCARDABLE
-	rsect.checkOffset(startoff)
-	rsect.pad(ctxt.Out, uint32(size))
-
-	pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = rsect.virtualAddress
-	pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = rsect.virtualSize
-}
-
-func (ctxt *Link) dope() {
-	initdynimport(ctxt)
-	initdynexport(ctxt)
-}
-
-func setpersrc(ctxt *Link, sym *sym.Symbol) {
-	if rsrcsym != nil {
-		Errorf(sym, "too many .rsrc sections")
-	}
-
-	rsrcsym = sym
-}
-
-func addpersrc(ctxt *Link) {
-	if rsrcsym == nil {
-		return
-	}
-
-	h := pefile.addSection(".rsrc", int(rsrcsym.Size), int(rsrcsym.Size))
-	h.characteristics = IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_CNT_INITIALIZED_DATA
-	h.checkOffset(ctxt.Out.Offset())
-
-	// relocation
-	for ri := range rsrcsym.R {
-		r := &rsrcsym.R[ri]
-		p := rsrcsym.P[r.Off:]
-		val := uint32(int64(h.virtualAddress) + r.Add)
-
-		// 32-bit little-endian
-		p[0] = byte(val)
-
-		p[1] = byte(val >> 8)
-		p[2] = byte(val >> 16)
-		p[3] = byte(val >> 24)
-	}
-
-	ctxt.Out.Write(rsrcsym.P)
-	h.pad(ctxt.Out, uint32(rsrcsym.Size))
-
-	// update data directory
-	pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress = h.virtualAddress
-
-	pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_RESOURCE].Size = h.virtualSize
-}
-
-func Asmbpe(ctxt *Link) {
-	switch ctxt.Arch.Family {
-	default:
-		Exitf("unknown PE architecture: %v", ctxt.Arch.Family)
-	case sys.AMD64, sys.I386, sys.ARM:
-	}
-
-	t := pefile.addSection(".text", int(Segtext.Length), int(Segtext.Length))
-	t.characteristics = IMAGE_SCN_CNT_CODE | IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ
-	if ctxt.LinkMode == LinkExternal {
-		// some data symbols (e.g. masks) end up in the .text section, and they normally
-		// expect larger alignment requirement than the default text section alignment.
-		t.characteristics |= IMAGE_SCN_ALIGN_32BYTES
-	}
-	t.checkSegment(&Segtext)
-	pefile.textSect = t
-
-	ro := pefile.addSection(".rdata", int(Segrodata.Length), int(Segrodata.Length))
-	ro.characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
-	if ctxt.LinkMode == LinkExternal {
-		// some data symbols (e.g. masks) end up in the .rdata section, and they normally
-		// expect larger alignment requirement than the default text section alignment.
-		ro.characteristics |= IMAGE_SCN_ALIGN_32BYTES
-	}
-	ro.checkSegment(&Segrodata)
-	pefile.rdataSect = ro
-
-	var d *peSection
-	if ctxt.LinkMode != LinkExternal {
-		d = pefile.addSection(".data", int(Segdata.Length), int(Segdata.Filelen))
-		d.characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE
-		d.checkSegment(&Segdata)
-		pefile.dataSect = d
-	} else {
-		d = pefile.addSection(".data", int(Segdata.Filelen), int(Segdata.Filelen))
-		d.characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_ALIGN_32BYTES
-		d.checkSegment(&Segdata)
-		pefile.dataSect = d
-
-		b := pefile.addSection(".bss", int(Segdata.Length-Segdata.Filelen), 0)
-		b.characteristics = IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_ALIGN_32BYTES
-		b.pointerToRawData = 0
-		pefile.bssSect = b
-	}
-
-	pefile.addDWARF()
-
-	if ctxt.LinkMode == LinkExternal {
-		pefile.ctorsSect = pefile.addInitArray(ctxt)
-	}
-
-	ctxt.Out.SeekSet(int64(pefile.nextFileOffset))
-	if ctxt.LinkMode != LinkExternal {
-		addimports(ctxt, d)
-		addexports(ctxt)
-		addPEBaseReloc(ctxt)
-	}
-	pefile.writeSymbolTableAndStringTable(ctxt)
-	addpersrc(ctxt)
-	if ctxt.LinkMode == LinkExternal {
-		pefile.emitRelocations(ctxt)
-	}
-
-	pewrite(ctxt)
-}
diff --git a/src/cmd/oldlink/internal/ld/sym.go b/src/cmd/oldlink/internal/ld/sym.go
deleted file mode 100644
index d5b3a5e..0000000
--- a/src/cmd/oldlink/internal/ld/sym.go
+++ /dev/null
@@ -1,109 +0,0 @@
-// Derived from Inferno utils/6l/obj.c and utils/6l/span.c
-// https://bitbucket.org/inferno-os/inferno-os/src/master/utils/6l/obj.c
-// https://bitbucket.org/inferno-os/inferno-os/src/master/utils/6l/span.c
-//
-//	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
-
-import (
-	"cmd/internal/objabi"
-	"cmd/internal/sys"
-	"cmd/oldlink/internal/sym"
-	"log"
-)
-
-func linknew(arch *sys.Arch) *Link {
-	ctxt := &Link{
-		Syms:         sym.NewSymbols(),
-		Out:          &OutBuf{arch: arch},
-		Arch:         arch,
-		LibraryByPkg: make(map[string]*sym.Library),
-	}
-
-	if objabi.GOARCH != arch.Name {
-		log.Fatalf("invalid objabi.GOARCH %s (want %s)", objabi.GOARCH, arch.Name)
-	}
-
-	AtExit(func() {
-		if nerrors > 0 && ctxt.Out.f != nil {
-			ctxt.Out.f.Close()
-			mayberemoveoutfile()
-		}
-	})
-
-	return ctxt
-}
-
-// computeTLSOffset records the thread-local storage offset.
-// Not used for Android where the TLS offset is determined at runtime.
-func (ctxt *Link) computeTLSOffset() {
-	switch ctxt.HeadType {
-	default:
-		log.Fatalf("unknown thread-local storage offset for %v", ctxt.HeadType)
-
-	case objabi.Hplan9, objabi.Hwindows, objabi.Hjs, objabi.Haix:
-		break
-
-	case objabi.Hlinux,
-		objabi.Hfreebsd,
-		objabi.Hnetbsd,
-		objabi.Hopenbsd,
-		objabi.Hdragonfly,
-		objabi.Hsolaris:
-		/*
-		 * ELF uses TLS offset negative from FS.
-		 * Translate 0(FS) and 8(FS) into -16(FS) and -8(FS).
-		 * Known to low-level assembly in package runtime and runtime/cgo.
-		 */
-		ctxt.Tlsoffset = -1 * ctxt.Arch.PtrSize
-
-	case objabi.Hdarwin:
-		/*
-		 * OS X system constants - offset from 0(GS) to our TLS.
-		 */
-		switch ctxt.Arch.Family {
-		default:
-			log.Fatalf("unknown thread-local storage offset for darwin/%s", ctxt.Arch.Name)
-
-			/*
-			 * For x86, Apple has reserved a slot in the TLS for Go. See issue 23617.
-			 * That slot is at offset 0x30 on amd64.
-			 * The slot will hold the G pointer.
-			 * These constants should match those in runtime/sys_darwin_{386,amd64}.s
-			 * and runtime/cgo/gcc_darwin_{386,amd64}.c.
-			 */
-		case sys.AMD64:
-			ctxt.Tlsoffset = 0x30
-
-		case sys.ARM64:
-			ctxt.Tlsoffset = 0 // dummy value, not needed
-		}
-	}
-
-}
diff --git a/src/cmd/oldlink/internal/ld/symtab.go b/src/cmd/oldlink/internal/ld/symtab.go
deleted file mode 100644
index 86c3c22b..0000000
--- a/src/cmd/oldlink/internal/ld/symtab.go
+++ /dev/null
@@ -1,713 +0,0 @@
-// Inferno utils/6l/span.c
-// https://bitbucket.org/inferno-os/inferno-os/src/master/utils/6l/span.c
-//
-//	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
-
-import (
-	"cmd/internal/objabi"
-	"cmd/internal/sys"
-	"cmd/oldlink/internal/sym"
-	"fmt"
-	"path/filepath"
-	"strings"
-)
-
-// Symbol table.
-
-func putelfstr(s string) int {
-	if len(Elfstrdat) == 0 && s != "" {
-		// first entry must be empty string
-		putelfstr("")
-	}
-
-	off := len(Elfstrdat)
-	Elfstrdat = append(Elfstrdat, s...)
-	Elfstrdat = append(Elfstrdat, 0)
-	return off
-}
-
-func putelfsyment(out *OutBuf, off int, addr int64, size int64, info int, shndx int, other int) {
-	if elf64 {
-		out.Write32(uint32(off))
-		out.Write8(uint8(info))
-		out.Write8(uint8(other))
-		out.Write16(uint16(shndx))
-		out.Write64(uint64(addr))
-		out.Write64(uint64(size))
-		Symsize += ELF64SYMSIZE
-	} else {
-		out.Write32(uint32(off))
-		out.Write32(uint32(addr))
-		out.Write32(uint32(size))
-		out.Write8(uint8(info))
-		out.Write8(uint8(other))
-		out.Write16(uint16(shndx))
-		Symsize += ELF32SYMSIZE
-	}
-}
-
-var numelfsym = 1 // 0 is reserved
-
-var elfbind int
-
-func putelfsym(ctxt *Link, x *sym.Symbol, s string, t SymbolType, addr int64, go_ *sym.Symbol) {
-	var typ int
-
-	switch t {
-	default:
-		return
-
-	case TextSym:
-		typ = STT_FUNC
-
-	case DataSym, BSSSym:
-		typ = STT_OBJECT
-
-	case UndefinedSym:
-		// ElfType is only set for symbols read from Go shared libraries, but
-		// for other symbols it is left as STT_NOTYPE which is fine.
-		typ = int(x.ElfType())
-
-	case TLSSym:
-		typ = STT_TLS
-	}
-
-	size := x.Size
-	if t == UndefinedSym {
-		size = 0
-	}
-
-	xo := x
-	for xo.Outer != nil {
-		xo = xo.Outer
-	}
-
-	var elfshnum int
-	if xo.Type == sym.SDYNIMPORT || xo.Type == sym.SHOSTOBJ || xo.Type == sym.SUNDEFEXT {
-		elfshnum = SHN_UNDEF
-	} else {
-		if xo.Sect == nil {
-			Errorf(x, "missing section in putelfsym")
-			return
-		}
-		if xo.Sect.Elfsect == nil {
-			Errorf(x, "missing ELF section in putelfsym")
-			return
-		}
-		elfshnum = xo.Sect.Elfsect.(*ElfShdr).shnum
-	}
-
-	// One pass for each binding: STB_LOCAL, STB_GLOBAL,
-	// maybe one day STB_WEAK.
-	bind := STB_GLOBAL
-
-	if x.IsFileLocal() || x.Attr.VisibilityHidden() || x.Attr.Local() {
-		bind = STB_LOCAL
-	}
-
-	// In external linking mode, we have to invoke gcc with -rdynamic
-	// to get the exported symbols put into the dynamic symbol table.
-	// To avoid filling the dynamic table with lots of unnecessary symbols,
-	// mark all Go symbols local (not global) in the final executable.
-	// But when we're dynamically linking, we need all those global symbols.
-	if !ctxt.DynlinkingGo() && ctxt.LinkMode == LinkExternal && !x.Attr.CgoExportStatic() && elfshnum != SHN_UNDEF {
-		bind = STB_LOCAL
-	}
-
-	if ctxt.LinkMode == LinkExternal && elfshnum != SHN_UNDEF {
-		addr -= int64(xo.Sect.Vaddr)
-	}
-	other := STV_DEFAULT
-	if x.Attr.VisibilityHidden() {
-		// TODO(mwhudson): We only set AttrVisibilityHidden in ldelf, i.e. when
-		// internally linking. But STV_HIDDEN visibility only matters in object
-		// files and shared libraries, and as we are a long way from implementing
-		// internal linking for shared libraries and only create object files when
-		// externally linking, I don't think this makes a lot of sense.
-		other = STV_HIDDEN
-	}
-	if ctxt.Arch.Family == sys.PPC64 && typ == STT_FUNC && x.Attr.Shared() && x.Name != "runtime.duffzero" && x.Name != "runtime.duffcopy" {
-		// On ppc64 the top three bits of the st_other field indicate how
-		// many instructions separate the global and local entry points. In
-		// our case it is two instructions, indicated by the value 3.
-		// The conditions here match those in preprocess in
-		// cmd/internal/obj/ppc64/obj9.go, which is where the
-		// instructions are inserted.
-		other |= 3 << 5
-	}
-
-	// When dynamically linking, we create Symbols by reading the names from
-	// the symbol tables of the shared libraries and so the names need to
-	// match exactly. Tools like DTrace will have to wait for now.
-	if !ctxt.DynlinkingGo() {
-		// Rewrite · to . for ASCII-only tools like DTrace (sigh)
-		s = strings.Replace(s, "·", ".", -1)
-	}
-
-	if ctxt.DynlinkingGo() && bind == STB_GLOBAL && elfbind == STB_LOCAL && x.Type == sym.STEXT {
-		// When dynamically linking, we want references to functions defined
-		// in this module to always be to the function object, not to the
-		// PLT. We force this by writing an additional local symbol for every
-		// global function symbol and making all relocations against the
-		// global symbol refer to this local symbol instead (see
-		// (*sym.Symbol).ElfsymForReloc). This is approximately equivalent to the
-		// ELF linker -Bsymbolic-functions option, but that is buggy on
-		// several platforms.
-		putelfsyment(ctxt.Out, putelfstr("local."+s), addr, size, STB_LOCAL<<4|typ&0xf, elfshnum, other)
-		x.LocalElfsym = int32(numelfsym)
-		numelfsym++
-		return
-	} else if bind != elfbind {
-		return
-	}
-
-	putelfsyment(ctxt.Out, putelfstr(s), addr, size, bind<<4|typ&0xf, elfshnum, other)
-	x.Elfsym = int32(numelfsym)
-	numelfsym++
-}
-
-func putelfsectionsym(out *OutBuf, s *sym.Symbol, shndx int) {
-	putelfsyment(out, 0, 0, 0, STB_LOCAL<<4|STT_SECTION, shndx, 0)
-	s.Elfsym = int32(numelfsym)
-	numelfsym++
-}
-
-func Asmelfsym(ctxt *Link) {
-	// the first symbol entry is reserved
-	putelfsyment(ctxt.Out, 0, 0, 0, STB_LOCAL<<4|STT_NOTYPE, 0, 0)
-
-	dwarfaddelfsectionsyms(ctxt)
-
-	// Some linkers will add a FILE sym if one is not present.
-	// Avoid having the working directory inserted into the symbol table.
-	// It is added with a name to avoid problems with external linking
-	// encountered on some versions of Solaris. See issue #14957.
-	putelfsyment(ctxt.Out, putelfstr("go.go"), 0, 0, STB_LOCAL<<4|STT_FILE, SHN_ABS, 0)
-	numelfsym++
-
-	elfbind = STB_LOCAL
-	genasmsym(ctxt, putelfsym)
-
-	elfbind = STB_GLOBAL
-	elfglobalsymndx = numelfsym
-	genasmsym(ctxt, putelfsym)
-}
-
-func putplan9sym(ctxt *Link, x *sym.Symbol, s string, typ SymbolType, addr int64, go_ *sym.Symbol) {
-	t := int(typ)
-	switch typ {
-	case TextSym, DataSym, BSSSym:
-		if x.IsFileLocal() {
-			t += 'a' - 'A'
-		}
-		fallthrough
-
-	case AutoSym, ParamSym, FrameSym:
-		l := 4
-		if ctxt.HeadType == objabi.Hplan9 && ctxt.Arch.Family == sys.AMD64 && !Flag8 {
-			ctxt.Out.Write32b(uint32(addr >> 32))
-			l = 8
-		}
-
-		ctxt.Out.Write32b(uint32(addr))
-		ctxt.Out.Write8(uint8(t + 0x80)) /* 0x80 is variable length */
-
-		ctxt.Out.WriteString(s)
-		ctxt.Out.Write8(0)
-
-		Symsize += int32(l) + 1 + int32(len(s)) + 1
-
-	default:
-		return
-	}
-}
-
-func Asmplan9sym(ctxt *Link) {
-	genasmsym(ctxt, putplan9sym)
-}
-
-var symt *sym.Symbol
-
-type byPkg []*sym.Library
-
-func (libs byPkg) Len() int {
-	return len(libs)
-}
-
-func (libs byPkg) Less(a, b int) bool {
-	return libs[a].Pkg < libs[b].Pkg
-}
-
-func (libs byPkg) Swap(a, b int) {
-	libs[a], libs[b] = libs[b], libs[a]
-}
-
-// Create a table with information on the text sections.
-
-func textsectionmap(ctxt *Link) uint32 {
-
-	t := ctxt.Syms.Lookup("runtime.textsectionmap", 0)
-	t.Type = sym.SRODATA
-	t.Attr |= sym.AttrReachable
-	nsections := int64(0)
-
-	for _, sect := range Segtext.Sections {
-		if sect.Name == ".text" {
-			nsections++
-		} else {
-			break
-		}
-	}
-	t.Grow(3 * nsections * int64(ctxt.Arch.PtrSize))
-
-	off := int64(0)
-	n := 0
-
-	// The vaddr for each text section is the difference between the section's
-	// Vaddr and the Vaddr for the first text section as determined at compile
-	// time.
-
-	// The symbol for the first text section is named runtime.text as before.
-	// Additional text sections are named runtime.text.n where n is the
-	// order of creation starting with 1. These symbols provide the section's
-	// address after relocation by the linker.
-
-	textbase := Segtext.Sections[0].Vaddr
-	for _, sect := range Segtext.Sections {
-		if sect.Name != ".text" {
-			break
-		}
-		off = t.SetUint(ctxt.Arch, off, sect.Vaddr-textbase)
-		off = t.SetUint(ctxt.Arch, off, sect.Length)
-		if n == 0 {
-			s := ctxt.Syms.ROLookup("runtime.text", 0)
-			if s == nil {
-				Errorf(nil, "Unable to find symbol runtime.text\n")
-			}
-			off = t.SetAddr(ctxt.Arch, off, s)
-
-		} else {
-			s := ctxt.Syms.Lookup(fmt.Sprintf("runtime.text.%d", n), 0)
-			if s == nil {
-				Errorf(nil, "Unable to find symbol runtime.text.%d\n", n)
-			}
-			off = t.SetAddr(ctxt.Arch, off, s)
-		}
-		n++
-	}
-	return uint32(n)
-}
-
-func (ctxt *Link) symtab() {
-	switch ctxt.BuildMode {
-	case BuildModeCArchive, BuildModeCShared:
-		for _, s := range ctxt.Syms.Allsym {
-			// Create a new entry in the .init_array section that points to the
-			// library initializer function.
-			if s.Name == *flagEntrySymbol && ctxt.HeadType != objabi.Haix {
-				addinitarrdata(ctxt, s)
-			}
-		}
-	}
-
-	// Define these so that they'll get put into the symbol table.
-	// data.c:/^address will provide the actual values.
-	ctxt.xdefine("runtime.text", sym.STEXT, 0)
-
-	ctxt.xdefine("runtime.etext", sym.STEXT, 0)
-	ctxt.xdefine("runtime.itablink", sym.SRODATA, 0)
-	ctxt.xdefine("runtime.eitablink", sym.SRODATA, 0)
-	ctxt.xdefine("runtime.rodata", sym.SRODATA, 0)
-	ctxt.xdefine("runtime.erodata", sym.SRODATA, 0)
-	ctxt.xdefine("runtime.types", sym.SRODATA, 0)
-	ctxt.xdefine("runtime.etypes", sym.SRODATA, 0)
-	ctxt.xdefine("runtime.noptrdata", sym.SNOPTRDATA, 0)
-	ctxt.xdefine("runtime.enoptrdata", sym.SNOPTRDATA, 0)
-	ctxt.xdefine("runtime.data", sym.SDATA, 0)
-	ctxt.xdefine("runtime.edata", sym.SDATA, 0)
-	ctxt.xdefine("runtime.bss", sym.SBSS, 0)
-	ctxt.xdefine("runtime.ebss", sym.SBSS, 0)
-	ctxt.xdefine("runtime.noptrbss", sym.SNOPTRBSS, 0)
-	ctxt.xdefine("runtime.enoptrbss", sym.SNOPTRBSS, 0)
-	ctxt.xdefine("runtime.end", sym.SBSS, 0)
-	ctxt.xdefine("runtime.epclntab", sym.SRODATA, 0)
-	ctxt.xdefine("runtime.esymtab", sym.SRODATA, 0)
-
-	// garbage collection symbols
-	s := ctxt.Syms.Lookup("runtime.gcdata", 0)
-
-	s.Type = sym.SRODATA
-	s.Size = 0
-	s.Attr |= sym.AttrReachable
-	ctxt.xdefine("runtime.egcdata", sym.SRODATA, 0)
-
-	s = ctxt.Syms.Lookup("runtime.gcbss", 0)
-	s.Type = sym.SRODATA
-	s.Size = 0
-	s.Attr |= sym.AttrReachable
-	ctxt.xdefine("runtime.egcbss", sym.SRODATA, 0)
-
-	// pseudo-symbols to mark locations of type, string, and go string data.
-	var symtype *sym.Symbol
-	var symtyperel *sym.Symbol
-	if !ctxt.DynlinkingGo() {
-		if ctxt.UseRelro() && (ctxt.BuildMode == BuildModeCArchive || ctxt.BuildMode == BuildModeCShared || ctxt.BuildMode == BuildModePIE) {
-			s = ctxt.Syms.Lookup("type.*", 0)
-
-			s.Type = sym.STYPE
-			s.Size = 0
-			s.Attr |= sym.AttrReachable
-			symtype = s
-
-			s = ctxt.Syms.Lookup("typerel.*", 0)
-
-			s.Type = sym.STYPERELRO
-			s.Size = 0
-			s.Attr |= sym.AttrReachable
-			symtyperel = s
-		} else {
-			s = ctxt.Syms.Lookup("type.*", 0)
-
-			s.Type = sym.STYPE
-			s.Size = 0
-			s.Attr |= sym.AttrReachable
-			symtype = s
-			symtyperel = s
-		}
-	}
-
-	groupSym := func(name string, t sym.SymKind) *sym.Symbol {
-		s := ctxt.Syms.Lookup(name, 0)
-		s.Type = t
-		s.Size = 0
-		s.Attr |= sym.AttrLocal | sym.AttrReachable
-		return s
-	}
-	var (
-		symgostring = groupSym("go.string.*", sym.SGOSTRING)
-		symgofunc   = groupSym("go.func.*", sym.SGOFUNC)
-		symgcbits   = groupSym("runtime.gcbits.*", sym.SGCBITS)
-	)
-
-	var symgofuncrel *sym.Symbol
-	if !ctxt.DynlinkingGo() {
-		if ctxt.UseRelro() {
-			symgofuncrel = groupSym("go.funcrel.*", sym.SGOFUNCRELRO)
-		} else {
-			symgofuncrel = symgofunc
-		}
-	}
-
-	symitablink := ctxt.Syms.Lookup("runtime.itablink", 0)
-	symitablink.Type = sym.SITABLINK
-
-	symt = ctxt.Syms.Lookup("runtime.symtab", 0)
-	symt.Attr |= sym.AttrLocal
-	symt.Type = sym.SSYMTAB
-	symt.Size = 0
-	symt.Attr |= sym.AttrReachable
-
-	nitablinks := 0
-
-	// assign specific types so that they sort together.
-	// within a type they sort by size, so the .* symbols
-	// just defined above will be first.
-	// hide the specific symbols.
-	for _, s := range ctxt.Syms.Allsym {
-		if ctxt.LinkMode != LinkExternal && isStaticTemp(s.Name) {
-			s.Attr |= sym.AttrNotInSymbolTable
-		}
-
-		if !s.Attr.Reachable() || s.Attr.Special() || s.Type != sym.SRODATA {
-			continue
-		}
-
-		switch {
-		case strings.HasPrefix(s.Name, "type."):
-			if !ctxt.DynlinkingGo() {
-				s.Attr |= sym.AttrNotInSymbolTable
-			}
-			if ctxt.UseRelro() {
-				s.Type = sym.STYPERELRO
-				s.Outer = symtyperel
-			} else {
-				s.Type = sym.STYPE
-				s.Outer = symtype
-			}
-
-		case strings.HasPrefix(s.Name, "go.importpath.") && ctxt.UseRelro():
-			// Keep go.importpath symbols in the same section as types and
-			// names, as they can be referred to by a section offset.
-			s.Type = sym.STYPERELRO
-
-		case strings.HasPrefix(s.Name, "go.itablink."):
-			nitablinks++
-			s.Type = sym.SITABLINK
-			s.Attr |= sym.AttrNotInSymbolTable
-			s.Outer = symitablink
-
-		case strings.HasPrefix(s.Name, "go.string."):
-			s.Type = sym.SGOSTRING
-			s.Attr |= sym.AttrNotInSymbolTable
-			s.Outer = symgostring
-
-		case strings.HasPrefix(s.Name, "runtime.gcbits."):
-			s.Type = sym.SGCBITS
-			s.Attr |= sym.AttrNotInSymbolTable
-			s.Outer = symgcbits
-
-		case strings.HasSuffix(s.Name, "·f"):
-			if !ctxt.DynlinkingGo() {
-				s.Attr |= sym.AttrNotInSymbolTable
-			}
-			if ctxt.UseRelro() {
-				s.Type = sym.SGOFUNCRELRO
-				s.Outer = symgofuncrel
-			} else {
-				s.Type = sym.SGOFUNC
-				s.Outer = symgofunc
-			}
-
-		case strings.HasPrefix(s.Name, "gcargs."),
-			strings.HasPrefix(s.Name, "gclocals."),
-			strings.HasPrefix(s.Name, "gclocals·"),
-			strings.HasPrefix(s.Name, "inltree."),
-			strings.HasSuffix(s.Name, ".opendefer"):
-			s.Type = sym.SGOFUNC
-			s.Attr |= sym.AttrNotInSymbolTable
-			s.Outer = symgofunc
-			s.Align = 4
-			liveness += (s.Size + int64(s.Align) - 1) &^ (int64(s.Align) - 1)
-		}
-	}
-
-	if ctxt.BuildMode == BuildModeShared {
-		abihashgostr := ctxt.Syms.Lookup("go.link.abihash."+filepath.Base(*flagOutfile), 0)
-		abihashgostr.Attr |= sym.AttrReachable
-		abihashgostr.Type = sym.SRODATA
-		hashsym := ctxt.Syms.Lookup("go.link.abihashbytes", 0)
-		abihashgostr.AddAddr(ctxt.Arch, hashsym)
-		abihashgostr.AddUint(ctxt.Arch, uint64(hashsym.Size))
-	}
-	if ctxt.BuildMode == BuildModePlugin || ctxt.CanUsePlugins() {
-		for _, l := range ctxt.Library {
-			s := ctxt.Syms.Lookup("go.link.pkghashbytes."+l.Pkg, 0)
-			s.Attr |= sym.AttrReachable
-			s.Type = sym.SRODATA
-			s.Size = int64(len(l.Hash))
-			s.P = []byte(l.Hash)
-			str := ctxt.Syms.Lookup("go.link.pkghash."+l.Pkg, 0)
-			str.Attr |= sym.AttrReachable
-			str.Type = sym.SRODATA
-			str.AddAddr(ctxt.Arch, s)
-			str.AddUint(ctxt.Arch, uint64(len(l.Hash)))
-		}
-	}
-
-	nsections := textsectionmap(ctxt)
-
-	// Information about the layout of the executable image for the
-	// runtime to use. Any changes here must be matched by changes to
-	// the definition of moduledata in runtime/symtab.go.
-	// This code uses several global variables that are set by pcln.go:pclntab.
-	moduledata := ctxt.Moduledata
-	// The pclntab slice
-	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.pclntab", 0))
-	moduledata.AddUint(ctxt.Arch, uint64(ctxt.Syms.Lookup("runtime.pclntab", 0).Size))
-	moduledata.AddUint(ctxt.Arch, uint64(ctxt.Syms.Lookup("runtime.pclntab", 0).Size))
-	// The ftab slice
-	moduledata.AddAddrPlus(ctxt.Arch, ctxt.Syms.Lookup("runtime.pclntab", 0), int64(pclntabPclntabOffset))
-	moduledata.AddUint(ctxt.Arch, uint64(pclntabNfunc+1))
-	moduledata.AddUint(ctxt.Arch, uint64(pclntabNfunc+1))
-	// The filetab slice
-	moduledata.AddAddrPlus(ctxt.Arch, ctxt.Syms.Lookup("runtime.pclntab", 0), int64(pclntabFiletabOffset))
-	moduledata.AddUint(ctxt.Arch, uint64(len(ctxt.Filesyms))+1)
-	moduledata.AddUint(ctxt.Arch, uint64(len(ctxt.Filesyms))+1)
-	// findfunctab
-	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.findfunctab", 0))
-	// minpc, maxpc
-	moduledata.AddAddr(ctxt.Arch, pclntabFirstFunc)
-	moduledata.AddAddrPlus(ctxt.Arch, pclntabLastFunc, pclntabLastFunc.Size)
-	// pointers to specific parts of the module
-	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.text", 0))
-	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.etext", 0))
-	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.noptrdata", 0))
-	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.enoptrdata", 0))
-	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.data", 0))
-	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.edata", 0))
-	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.bss", 0))
-	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.ebss", 0))
-	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.noptrbss", 0))
-	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.enoptrbss", 0))
-	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.end", 0))
-	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.gcdata", 0))
-	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.gcbss", 0))
-	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.types", 0))
-	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.etypes", 0))
-
-	if ctxt.HeadType == objabi.Haix && ctxt.LinkMode == LinkExternal {
-		// Add R_REF relocation to prevent ld's garbage collection of
-		// runtime.rodata, runtime.erodata and runtime.epclntab.
-		addRef := func(name string) {
-			r := moduledata.AddRel()
-			r.Sym = ctxt.Syms.Lookup(name, 0)
-			r.Type = objabi.R_XCOFFREF
-			r.Siz = uint8(ctxt.Arch.PtrSize)
-		}
-		addRef("runtime.rodata")
-		addRef("runtime.erodata")
-		addRef("runtime.epclntab")
-	}
-
-	// text section information
-	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.textsectionmap", 0))
-	moduledata.AddUint(ctxt.Arch, uint64(nsections))
-	moduledata.AddUint(ctxt.Arch, uint64(nsections))
-
-	// The typelinks slice
-	typelinkSym := ctxt.Syms.Lookup("runtime.typelink", 0)
-	ntypelinks := uint64(typelinkSym.Size) / 4
-	moduledata.AddAddr(ctxt.Arch, typelinkSym)
-	moduledata.AddUint(ctxt.Arch, ntypelinks)
-	moduledata.AddUint(ctxt.Arch, ntypelinks)
-	// The itablinks slice
-	moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.itablink", 0))
-	moduledata.AddUint(ctxt.Arch, uint64(nitablinks))
-	moduledata.AddUint(ctxt.Arch, uint64(nitablinks))
-	// The ptab slice
-	if ptab := ctxt.Syms.ROLookup("go.plugin.tabs", 0); ptab != nil && ptab.Attr.Reachable() {
-		ptab.Attr |= sym.AttrLocal
-		ptab.Type = sym.SRODATA
-
-		nentries := uint64(len(ptab.P) / 8) // sizeof(nameOff) + sizeof(typeOff)
-		moduledata.AddAddr(ctxt.Arch, ptab)
-		moduledata.AddUint(ctxt.Arch, nentries)
-		moduledata.AddUint(ctxt.Arch, nentries)
-	} else {
-		moduledata.AddUint(ctxt.Arch, 0)
-		moduledata.AddUint(ctxt.Arch, 0)
-		moduledata.AddUint(ctxt.Arch, 0)
-	}
-	if ctxt.BuildMode == BuildModePlugin {
-		addgostring(ctxt, moduledata, "go.link.thispluginpath", objabi.PathToPrefix(*flagPluginPath))
-
-		pkghashes := ctxt.Syms.Lookup("go.link.pkghashes", 0)
-		pkghashes.Attr |= sym.AttrReachable
-		pkghashes.Attr |= sym.AttrLocal
-		pkghashes.Type = sym.SRODATA
-
-		for i, l := range ctxt.Library {
-			// pkghashes[i].name
-			addgostring(ctxt, pkghashes, fmt.Sprintf("go.link.pkgname.%d", i), l.Pkg)
-			// pkghashes[i].linktimehash
-			addgostring(ctxt, pkghashes, fmt.Sprintf("go.link.pkglinkhash.%d", i), l.Hash)
-			// pkghashes[i].runtimehash
-			hash := ctxt.Syms.ROLookup("go.link.pkghash."+l.Pkg, 0)
-			pkghashes.AddAddr(ctxt.Arch, hash)
-		}
-		moduledata.AddAddr(ctxt.Arch, pkghashes)
-		moduledata.AddUint(ctxt.Arch, uint64(len(ctxt.Library)))
-		moduledata.AddUint(ctxt.Arch, uint64(len(ctxt.Library)))
-	} else {
-		moduledata.AddUint(ctxt.Arch, 0) // pluginpath
-		moduledata.AddUint(ctxt.Arch, 0)
-		moduledata.AddUint(ctxt.Arch, 0) // pkghashes slice
-		moduledata.AddUint(ctxt.Arch, 0)
-		moduledata.AddUint(ctxt.Arch, 0)
-	}
-	if len(ctxt.Shlibs) > 0 {
-		thismodulename := filepath.Base(*flagOutfile)
-		switch ctxt.BuildMode {
-		case BuildModeExe, BuildModePIE:
-			// When linking an executable, outfile is just "a.out". Make
-			// it something slightly more comprehensible.
-			thismodulename = "the executable"
-		}
-		addgostring(ctxt, moduledata, "go.link.thismodulename", thismodulename)
-
-		modulehashes := ctxt.Syms.Lookup("go.link.abihashes", 0)
-		modulehashes.Attr |= sym.AttrReachable
-		modulehashes.Attr |= sym.AttrLocal
-		modulehashes.Type = sym.SRODATA
-
-		for i, shlib := range ctxt.Shlibs {
-			// modulehashes[i].modulename
-			modulename := filepath.Base(shlib.Path)
-			addgostring(ctxt, modulehashes, fmt.Sprintf("go.link.libname.%d", i), modulename)
-
-			// modulehashes[i].linktimehash
-			addgostring(ctxt, modulehashes, fmt.Sprintf("go.link.linkhash.%d", i), string(shlib.Hash))
-
-			// modulehashes[i].runtimehash
-			abihash := ctxt.Syms.Lookup("go.link.abihash."+modulename, 0)
-			abihash.Attr |= sym.AttrReachable
-			modulehashes.AddAddr(ctxt.Arch, abihash)
-		}
-
-		moduledata.AddAddr(ctxt.Arch, modulehashes)
-		moduledata.AddUint(ctxt.Arch, uint64(len(ctxt.Shlibs)))
-		moduledata.AddUint(ctxt.Arch, uint64(len(ctxt.Shlibs)))
-	} else {
-		moduledata.AddUint(ctxt.Arch, 0) // modulename
-		moduledata.AddUint(ctxt.Arch, 0)
-		moduledata.AddUint(ctxt.Arch, 0) // moduleshashes slice
-		moduledata.AddUint(ctxt.Arch, 0)
-		moduledata.AddUint(ctxt.Arch, 0)
-	}
-
-	hasmain := ctxt.BuildMode == BuildModeExe || ctxt.BuildMode == BuildModePIE
-	if hasmain {
-		moduledata.AddUint8(1)
-	} else {
-		moduledata.AddUint8(0)
-	}
-
-	// The rest of moduledata is zero initialized.
-	// When linking an object that does not contain the runtime we are
-	// creating the moduledata from scratch and it does not have a
-	// compiler-provided size, so read it from the type data.
-	moduledatatype := ctxt.Syms.ROLookup("type.runtime.moduledata", 0)
-	moduledata.Size = decodetypeSize(ctxt.Arch, moduledatatype.P)
-	moduledata.Grow(moduledata.Size)
-
-	lastmoduledatap := ctxt.Syms.Lookup("runtime.lastmoduledatap", 0)
-	if lastmoduledatap.Type != sym.SDYNIMPORT {
-		lastmoduledatap.Type = sym.SNOPTRDATA
-		lastmoduledatap.Size = 0 // overwrite existing value
-		lastmoduledatap.AddAddr(ctxt.Arch, moduledata)
-	}
-}
-
-func isStaticTemp(name string) bool {
-	if i := strings.LastIndex(name, "/"); i >= 0 {
-		name = name[i:]
-	}
-	return strings.Contains(name, "..stmp_")
-}
diff --git a/src/cmd/oldlink/internal/ld/testdata/httptest/main/main.go b/src/cmd/oldlink/internal/ld/testdata/httptest/main/main.go
deleted file mode 100644
index 1bce301..0000000
--- a/src/cmd/oldlink/internal/ld/testdata/httptest/main/main.go
+++ /dev/null
@@ -1,22 +0,0 @@
-// A small test program that uses the net/http package. There is
-// nothing special about net/http here, this is just a convenient way
-// to pull in a lot of code.
-
-package main
-
-import (
-	"net/http"
-	"net/http/httptest"
-)
-
-type statusHandler int
-
-func (h *statusHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
-	w.WriteHeader(int(*h))
-}
-
-func main() {
-	status := statusHandler(http.StatusNotFound)
-	s := httptest.NewServer(&status)
-	defer s.Close()
-}
diff --git a/src/cmd/oldlink/internal/ld/testdata/issue10978/main.go b/src/cmd/oldlink/internal/ld/testdata/issue10978/main.go
deleted file mode 100644
index 5e8c097..0000000
--- a/src/cmd/oldlink/internal/ld/testdata/issue10978/main.go
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright 2018 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 main
-
-func undefined()
-
-func defined1() int {
-	// To check multiple errors for a single symbol,
-	// reference undefined more than once.
-	undefined()
-	undefined()
-	return 0
-}
-
-func defined2() {
-	undefined()
-	undefined()
-}
-
-func init() {
-	_ = defined1()
-	defined2()
-}
-
-// The "main" function remains undeclared.
diff --git a/src/cmd/oldlink/internal/ld/testdata/issue10978/main.s b/src/cmd/oldlink/internal/ld/testdata/issue10978/main.s
deleted file mode 100644
index 1d00e76..0000000
--- a/src/cmd/oldlink/internal/ld/testdata/issue10978/main.s
+++ /dev/null
@@ -1 +0,0 @@
-// This file is needed to make "go build" work for package with external functions.

diff --git a/src/cmd/oldlink/internal/ld/testdata/issue25459/a/a.go b/src/cmd/oldlink/internal/ld/testdata/issue25459/a/a.go
deleted file mode 100644
index 6032d76..0000000
--- a/src/cmd/oldlink/internal/ld/testdata/issue25459/a/a.go
+++ /dev/null
@@ -1,27 +0,0 @@
-package a
-
-const Always = true
-
-var Count int
-
-type FuncReturningInt func() int
-
-var PointerToConstIf FuncReturningInt
-
-func ConstIf() int {
-	if Always {
-		return 1
-	}
-	var imdead [4]int
-	imdead[Count] = 1
-	return imdead[0]
-}
-
-func CallConstIf() int {
-	Count += 3
-	return ConstIf()
-}
-
-func Another() {
-	defer func() { PointerToConstIf = ConstIf; Count += 1 }()
-}
diff --git a/src/cmd/oldlink/internal/ld/testdata/issue25459/main/main.go b/src/cmd/oldlink/internal/ld/testdata/issue25459/main/main.go
deleted file mode 100644
index 3f5f365..0000000
--- a/src/cmd/oldlink/internal/ld/testdata/issue25459/main/main.go
+++ /dev/null
@@ -1,10 +0,0 @@
-package main
-
-import "cmd/oldlink/internal/ld/testdata/issue25459/a"
-
-var Glob int
-
-func main() {
-	a.Another()
-	Glob += a.ConstIf() + a.CallConstIf()
-}
diff --git a/src/cmd/oldlink/internal/ld/testdata/issue26237/b.dir/b.go b/src/cmd/oldlink/internal/ld/testdata/issue26237/b.dir/b.go
deleted file mode 100644
index ca57749..0000000
--- a/src/cmd/oldlink/internal/ld/testdata/issue26237/b.dir/b.go
+++ /dev/null
@@ -1,16 +0,0 @@
-package b
-
-var q int
-
-func Top(x int) int {
-	q += 1
-	if q != x {
-		return 3
-	}
-	return 4
-}
-
-func OOO(x int) int {
-	defer func() { q += x & 7 }()
-	return Top(x + 1)
-}
diff --git a/src/cmd/oldlink/internal/ld/testdata/issue26237/main/main.go b/src/cmd/oldlink/internal/ld/testdata/issue26237/main/main.go
deleted file mode 100644
index 88b54f1..0000000
--- a/src/cmd/oldlink/internal/ld/testdata/issue26237/main/main.go
+++ /dev/null
@@ -1,16 +0,0 @@
-package main
-
-import (
-	"fmt"
-
-	b "cmd/oldlink/internal/ld/testdata/issue26237/b.dir"
-)
-
-var skyx int
-
-func main() {
-	skyx += b.OOO(skyx)
-	if b.Top(1) == 99 {
-		fmt.Printf("Beware the Jabberwock, my son!\n")
-	}
-}
diff --git a/src/cmd/oldlink/internal/ld/testdata/issue32233/lib/ObjC.m b/src/cmd/oldlink/internal/ld/testdata/issue32233/lib/ObjC.m
deleted file mode 100644
index 9462788..0000000
--- a/src/cmd/oldlink/internal/ld/testdata/issue32233/lib/ObjC.m
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2019 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.
-
-#import <Foundation/Foundation.h>
-#import <AppKit/NSAppearance.h>
-
-BOOL function(void) {
-#if defined(MAC_OS_X_VERSION_MIN_REQUIRED) && (MAC_OS_X_VERSION_MIN_REQUIRED > 101300)
-  NSAppearance *darkAppearance;
-  if (@available(macOS 10.14, *)) {
-    darkAppearance = [NSAppearance appearanceNamed:NSAppearanceNameDarkAqua];
-  }
-#endif
-  return NO;
-}
diff --git a/src/cmd/oldlink/internal/ld/testdata/issue32233/lib/lib.go b/src/cmd/oldlink/internal/ld/testdata/issue32233/lib/lib.go
deleted file mode 100644
index 514b9b9..0000000
--- a/src/cmd/oldlink/internal/ld/testdata/issue32233/lib/lib.go
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2019 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 lib
-
-/*
-#cgo darwin CFLAGS: -D__MAC_OS_X_VERSION_MAX_ALLOWED=101450
-#cgo darwin LDFLAGS: -framework Foundation -framework AppKit
-#include "stdlib.h"
-int function(void);
-*/
-import "C"
-import "fmt"
-
-func DoC() {
-	C.function()
-	fmt.Println("called c function")
-}
diff --git a/src/cmd/oldlink/internal/ld/testdata/issue32233/main/main.go b/src/cmd/oldlink/internal/ld/testdata/issue32233/main/main.go
deleted file mode 100644
index 9eec6cc..0000000
--- a/src/cmd/oldlink/internal/ld/testdata/issue32233/main/main.go
+++ /dev/null
@@ -1,11 +0,0 @@
-// Copyright 2019 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 main
-
-import "cmd/oldlink/internal/ld/testdata/issue32233/lib"
-
-func main() {
-	lib.DoC()
-}
diff --git a/src/cmd/oldlink/internal/ld/typelink.go b/src/cmd/oldlink/internal/ld/typelink.go
deleted file mode 100644
index 07d04bb..0000000
--- a/src/cmd/oldlink/internal/ld/typelink.go
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright 2016 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/objabi"
-	"cmd/oldlink/internal/sym"
-	"sort"
-)
-
-type byTypeStr []typelinkSortKey
-
-type typelinkSortKey struct {
-	TypeStr string
-	Type    *sym.Symbol
-}
-
-func (s byTypeStr) Less(i, j int) bool { return s[i].TypeStr < s[j].TypeStr }
-func (s byTypeStr) Len() int           { return len(s) }
-func (s byTypeStr) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
-
-// typelink generates the typelink table which is used by reflect.typelinks().
-// Types that should be added to the typelinks table are marked with the
-// MakeTypelink attribute by the compiler.
-func (ctxt *Link) typelink() {
-	typelinks := byTypeStr{}
-	for _, s := range ctxt.Syms.Allsym {
-		if s.Attr.Reachable() && s.Attr.MakeTypelink() {
-			typelinks = append(typelinks, typelinkSortKey{decodetypeStr(ctxt.Arch, s), s})
-		}
-	}
-	sort.Sort(typelinks)
-
-	tl := ctxt.Syms.Lookup("runtime.typelink", 0)
-	tl.Type = sym.STYPELINK
-	tl.Attr |= sym.AttrReachable | sym.AttrLocal
-	tl.Size = int64(4 * len(typelinks))
-	tl.P = make([]byte, tl.Size)
-	tl.R = make([]sym.Reloc, len(typelinks))
-	for i, s := range typelinks {
-		r := &tl.R[i]
-		r.Sym = s.Type
-		r.Off = int32(i * 4)
-		r.Siz = 4
-		r.Type = objabi.R_ADDROFF
-	}
-}
diff --git a/src/cmd/oldlink/internal/ld/util.go b/src/cmd/oldlink/internal/ld/util.go
deleted file mode 100644
index 97c9a44..0000000
--- a/src/cmd/oldlink/internal/ld/util.go
+++ /dev/null
@@ -1,97 +0,0 @@
-// Copyright 2015 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/oldlink/internal/sym"
-	"encoding/binary"
-	"fmt"
-	"os"
-)
-
-var atExitFuncs []func()
-
-func AtExit(f func()) {
-	atExitFuncs = append(atExitFuncs, f)
-}
-
-// runAtExitFuncs runs the queued set of AtExit functions.
-func runAtExitFuncs() {
-	for i := len(atExitFuncs) - 1; i >= 0; i-- {
-		atExitFuncs[i]()
-	}
-	atExitFuncs = nil
-}
-
-// Exit exits with code after executing all atExitFuncs.
-func Exit(code int) {
-	runAtExitFuncs()
-	os.Exit(code)
-}
-
-// Exitf logs an error message then calls Exit(2).
-func Exitf(format string, a ...interface{}) {
-	fmt.Fprintf(os.Stderr, os.Args[0]+": "+format+"\n", a...)
-	nerrors++
-	Exit(2)
-}
-
-// Errorf 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.
-func Errorf(s *sym.Symbol, format string, args ...interface{}) {
-	if s != nil {
-		format = s.Name + ": " + format
-	}
-	format += "\n"
-	fmt.Fprintf(os.Stderr, format, args...)
-	nerrors++
-	if *flagH {
-		panic("error")
-	}
-	if nerrors > 20 {
-		Exitf("too many errors")
-	}
-}
-
-func artrim(x []byte) string {
-	i := 0
-	j := len(x)
-	for i < len(x) && x[i] == ' ' {
-		i++
-	}
-	for j > i && x[j-1] == ' ' {
-		j--
-	}
-	return string(x[i:j])
-}
-
-func stringtouint32(x []uint32, s string) {
-	for i := 0; len(s) > 0; i++ {
-		var buf [4]byte
-		s = s[copy(buf[:], s):]
-		x[i] = binary.LittleEndian.Uint32(buf[:])
-	}
-}
-
-// contains reports whether v is in s.
-func contains(s []string, v string) bool {
-	for _, x := range s {
-		if x == v {
-			return true
-		}
-	}
-	return false
-}
-
-// implements sort.Interface, for sorting symbols by name.
-type byName []*sym.Symbol
-
-func (s byName) Len() int           { return len(s) }
-func (s byName) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
-func (s byName) Less(i, j int) bool { return s[i].Name < s[j].Name }
diff --git a/src/cmd/oldlink/internal/ld/xcoff.go b/src/cmd/oldlink/internal/ld/xcoff.go
deleted file mode 100644
index 4d66d6d..0000000
--- a/src/cmd/oldlink/internal/ld/xcoff.go
+++ /dev/null
@@ -1,1685 +0,0 @@
-// Copyright 2018 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 (
-	"bytes"
-	"cmd/internal/objabi"
-	"cmd/oldlink/internal/sym"
-	"encoding/binary"
-	"io/ioutil"
-	"math/bits"
-	"path/filepath"
-	"sort"
-	"strings"
-)
-
-// This file handles all algorithms related to XCOFF files generation.
-// Most of them are adaptations of the ones in  cmd/oldlink/internal/pe.go
-// as PE and XCOFF are based on COFF files.
-// XCOFF files generated are 64 bits.
-
-const (
-	// Total amount of space to reserve at the start of the file
-	// for File Header, Auxiliary Header, and Section Headers.
-	// May waste some.
-	XCOFFHDRRESERVE       = FILHSZ_64 + AOUTHSZ_EXEC64 + SCNHSZ_64*23
-	XCOFFSECTALIGN  int64 = 32 // base on dump -o
-
-	// XCOFF binaries should normally have all its sections position-independent.
-	// However, this is not yet possible for .text because of some R_ADDR relocations
-	// inside RODATA symbols.
-	// .data and .bss are position-independent so their address start inside a unreachable
-	// segment during execution to force segfault if something is wrong.
-	XCOFFTEXTBASE = 0x100000000 // Start of text address
-	XCOFFDATABASE = 0x200000000 // Start of data address
-)
-
-// File Header
-type XcoffFileHdr64 struct {
-	Fmagic   uint16 // Target machine
-	Fnscns   uint16 // Number of sections
-	Ftimedat int32  // Time and date of file creation
-	Fsymptr  uint64 // Byte offset to symbol table start
-	Fopthdr  uint16 // Number of bytes in optional header
-	Fflags   uint16 // Flags
-	Fnsyms   int32  // Number of entries in symbol table
-}
-
-const (
-	U64_TOCMAGIC = 0767 // AIX 64-bit XCOFF
-)
-
-// Flags that describe the type of the object file.
-const (
-	F_RELFLG    = 0x0001
-	F_EXEC      = 0x0002
-	F_LNNO      = 0x0004
-	F_FDPR_PROF = 0x0010
-	F_FDPR_OPTI = 0x0020
-	F_DSA       = 0x0040
-	F_VARPG     = 0x0100
-	F_DYNLOAD   = 0x1000
-	F_SHROBJ    = 0x2000
-	F_LOADONLY  = 0x4000
-)
-
-// Auxiliary Header
-type XcoffAoutHdr64 struct {
-	Omagic      int16    // Flags - Ignored If Vstamp Is 1
-	Ovstamp     int16    // Version
-	Odebugger   uint32   // Reserved For Debugger
-	Otextstart  uint64   // Virtual Address Of Text
-	Odatastart  uint64   // Virtual Address Of Data
-	Otoc        uint64   // Toc Address
-	Osnentry    int16    // Section Number For Entry Point
-	Osntext     int16    // Section Number For Text
-	Osndata     int16    // Section Number For Data
-	Osntoc      int16    // Section Number For Toc
-	Osnloader   int16    // Section Number For Loader
-	Osnbss      int16    // Section Number For Bss
-	Oalgntext   int16    // Max Text Alignment
-	Oalgndata   int16    // Max Data Alignment
-	Omodtype    [2]byte  // Module Type Field
-	Ocpuflag    uint8    // Bit Flags - Cputypes Of Objects
-	Ocputype    uint8    // Reserved for CPU type
-	Otextpsize  uint8    // Requested text page size
-	Odatapsize  uint8    // Requested data page size
-	Ostackpsize uint8    // Requested stack page size
-	Oflags      uint8    // Flags And TLS Alignment
-	Otsize      uint64   // Text Size In Bytes
-	Odsize      uint64   // Data Size In Bytes
-	Obsize      uint64   // Bss Size In Bytes
-	Oentry      uint64   // Entry Point Address
-	Omaxstack   uint64   // Max Stack Size Allowed
-	Omaxdata    uint64   // Max Data Size Allowed
-	Osntdata    int16    // Section Number For Tdata Section
-	Osntbss     int16    // Section Number For Tbss Section
-	Ox64flags   uint16   // Additional Flags For 64-Bit Objects
-	Oresv3a     int16    // Reserved
-	Oresv3      [2]int32 // Reserved
-}
-
-// Section Header
-type XcoffScnHdr64 struct {
-	Sname    [8]byte // Section Name
-	Spaddr   uint64  // Physical Address
-	Svaddr   uint64  // Virtual Address
-	Ssize    uint64  // Section Size
-	Sscnptr  uint64  // File Offset To Raw Data
-	Srelptr  uint64  // File Offset To Relocation
-	Slnnoptr uint64  // File Offset To Line Numbers
-	Snreloc  uint32  // Number Of Relocation Entries
-	Snlnno   uint32  // Number Of Line Number Entries
-	Sflags   uint32  // flags
-}
-
-// Flags defining the section type.
-const (
-	STYP_DWARF  = 0x0010
-	STYP_TEXT   = 0x0020
-	STYP_DATA   = 0x0040
-	STYP_BSS    = 0x0080
-	STYP_EXCEPT = 0x0100
-	STYP_INFO   = 0x0200
-	STYP_TDATA  = 0x0400
-	STYP_TBSS   = 0x0800
-	STYP_LOADER = 0x1000
-	STYP_DEBUG  = 0x2000
-	STYP_TYPCHK = 0x4000
-	STYP_OVRFLO = 0x8000
-)
-const (
-	SSUBTYP_DWINFO  = 0x10000 // DWARF info section
-	SSUBTYP_DWLINE  = 0x20000 // DWARF line-number section
-	SSUBTYP_DWPBNMS = 0x30000 // DWARF public names section
-	SSUBTYP_DWPBTYP = 0x40000 // DWARF public types section
-	SSUBTYP_DWARNGE = 0x50000 // DWARF aranges section
-	SSUBTYP_DWABREV = 0x60000 // DWARF abbreviation section
-	SSUBTYP_DWSTR   = 0x70000 // DWARF strings section
-	SSUBTYP_DWRNGES = 0x80000 // DWARF ranges section
-	SSUBTYP_DWLOC   = 0x90000 // DWARF location lists section
-	SSUBTYP_DWFRAME = 0xA0000 // DWARF frames section
-	SSUBTYP_DWMAC   = 0xB0000 // DWARF macros section
-)
-
-// Headers size
-const (
-	FILHSZ_32      = 20
-	FILHSZ_64      = 24
-	AOUTHSZ_EXEC32 = 72
-	AOUTHSZ_EXEC64 = 120
-	SCNHSZ_32      = 40
-	SCNHSZ_64      = 72
-	LDHDRSZ_32     = 32
-	LDHDRSZ_64     = 56
-	LDSYMSZ_64     = 24
-	RELSZ_64       = 14
-)
-
-// Type representing all XCOFF symbols.
-type xcoffSym interface {
-}
-
-// Symbol Table Entry
-type XcoffSymEnt64 struct {
-	Nvalue  uint64 // Symbol value
-	Noffset uint32 // Offset of the name in string table or .debug section
-	Nscnum  int16  // Section number of symbol
-	Ntype   uint16 // Basic and derived type specification
-	Nsclass uint8  // Storage class of symbol
-	Nnumaux int8   // Number of auxiliary entries
-}
-
-const SYMESZ = 18
-
-const (
-	// Nscnum
-	N_DEBUG = -2
-	N_ABS   = -1
-	N_UNDEF = 0
-
-	//Ntype
-	SYM_V_INTERNAL  = 0x1000
-	SYM_V_HIDDEN    = 0x2000
-	SYM_V_PROTECTED = 0x3000
-	SYM_V_EXPORTED  = 0x4000
-	SYM_TYPE_FUNC   = 0x0020 // is function
-)
-
-// Storage Class.
-const (
-	C_NULL    = 0   // Symbol table entry marked for deletion
-	C_EXT     = 2   // External symbol
-	C_STAT    = 3   // Static symbol
-	C_BLOCK   = 100 // Beginning or end of inner block
-	C_FCN     = 101 // Beginning or end of function
-	C_FILE    = 103 // Source file name and compiler information
-	C_HIDEXT  = 107 // Unnamed external symbol
-	C_BINCL   = 108 // Beginning of include file
-	C_EINCL   = 109 // End of include file
-	C_WEAKEXT = 111 // Weak external symbol
-	C_DWARF   = 112 // DWARF symbol
-	C_GSYM    = 128 // Global variable
-	C_LSYM    = 129 // Automatic variable allocated on stack
-	C_PSYM    = 130 // Argument to subroutine allocated on stack
-	C_RSYM    = 131 // Register variable
-	C_RPSYM   = 132 // Argument to function or procedure stored in register
-	C_STSYM   = 133 // Statically allocated symbol
-	C_BCOMM   = 135 // Beginning of common block
-	C_ECOML   = 136 // Local member of common block
-	C_ECOMM   = 137 // End of common block
-	C_DECL    = 140 // Declaration of object
-	C_ENTRY   = 141 // Alternate entry
-	C_FUN     = 142 // Function or procedure
-	C_BSTAT   = 143 // Beginning of static block
-	C_ESTAT   = 144 // End of static block
-	C_GTLS    = 145 // Global thread-local variable
-	C_STTLS   = 146 // Static thread-local variable
-)
-
-// File Auxiliary Entry
-type XcoffAuxFile64 struct {
-	Xzeroes  uint32 // The name is always in the string table
-	Xoffset  uint32 // Offset in the string table
-	X_pad1   [6]byte
-	Xftype   uint8 // Source file string type
-	X_pad2   [2]byte
-	Xauxtype uint8 // Type of auxiliary entry
-}
-
-// Function Auxiliary Entry
-type XcoffAuxFcn64 struct {
-	Xlnnoptr uint64 // File pointer to line number
-	Xfsize   uint32 // Size of function in bytes
-	Xendndx  uint32 // Symbol table index of next entry
-	Xpad     uint8  // Unused
-	Xauxtype uint8  // Type of auxiliary entry
-}
-
-// csect Auxiliary Entry.
-type XcoffAuxCSect64 struct {
-	Xscnlenlo uint32 // Lower 4 bytes of length or symbol table index
-	Xparmhash uint32 // Offset of parameter type-check string
-	Xsnhash   uint16 // .typchk section number
-	Xsmtyp    uint8  // Symbol alignment and type
-	Xsmclas   uint8  // Storage-mapping class
-	Xscnlenhi uint32 // Upper 4 bytes of length or symbol table index
-	Xpad      uint8  // Unused
-	Xauxtype  uint8  // Type of auxiliary entry
-}
-
-// DWARF Auxiliary Entry
-type XcoffAuxDWARF64 struct {
-	Xscnlen  uint64 // Length of this symbol section
-	X_pad    [9]byte
-	Xauxtype uint8 // Type of auxiliary entry
-}
-
-// Auxiliary type
-const (
-	_AUX_EXCEPT = 255
-	_AUX_FCN    = 254
-	_AUX_SYM    = 253
-	_AUX_FILE   = 252
-	_AUX_CSECT  = 251
-	_AUX_SECT   = 250
-)
-
-// Xftype field
-const (
-	XFT_FN = 0   // Source File Name
-	XFT_CT = 1   // Compile Time Stamp
-	XFT_CV = 2   // Compiler Version Number
-	XFT_CD = 128 // Compiler Defined Information/
-
-)
-
-// Symbol type field.
-const (
-	XTY_ER  = 0    // External reference
-	XTY_SD  = 1    // Section definition
-	XTY_LD  = 2    // Label definition
-	XTY_CM  = 3    // Common csect definition
-	XTY_WK  = 0x8  // Weak symbol
-	XTY_EXP = 0x10 // Exported symbol
-	XTY_ENT = 0x20 // Entry point symbol
-	XTY_IMP = 0x40 // Imported symbol
-)
-
-// Storage-mapping class.
-const (
-	XMC_PR     = 0  // Program code
-	XMC_RO     = 1  // Read-only constant
-	XMC_DB     = 2  // Debug dictionary table
-	XMC_TC     = 3  // TOC entry
-	XMC_UA     = 4  // Unclassified
-	XMC_RW     = 5  // Read/Write data
-	XMC_GL     = 6  // Global linkage
-	XMC_XO     = 7  // Extended operation
-	XMC_SV     = 8  // 32-bit supervisor call descriptor
-	XMC_BS     = 9  // BSS class
-	XMC_DS     = 10 // Function descriptor
-	XMC_UC     = 11 // Unnamed FORTRAN common
-	XMC_TC0    = 15 // TOC anchor
-	XMC_TD     = 16 // Scalar data entry in the TOC
-	XMC_SV64   = 17 // 64-bit supervisor call descriptor
-	XMC_SV3264 = 18 // Supervisor call descriptor for both 32-bit and 64-bit
-	XMC_TL     = 20 // Read/Write thread-local data
-	XMC_UL     = 21 // Read/Write thread-local data (.tbss)
-	XMC_TE     = 22 // TOC entry
-)
-
-// Loader Header
-type XcoffLdHdr64 struct {
-	Lversion int32  // Loader section version number
-	Lnsyms   int32  // Number of symbol table entries
-	Lnreloc  int32  // Number of relocation table entries
-	Listlen  uint32 // Length of import file ID string table
-	Lnimpid  int32  // Number of import file IDs
-	Lstlen   uint32 // Length of string table
-	Limpoff  uint64 // Offset to start of import file IDs
-	Lstoff   uint64 // Offset to start of string table
-	Lsymoff  uint64 // Offset to start of symbol table
-	Lrldoff  uint64 // Offset to start of relocation entries
-}
-
-// Loader Symbol
-type XcoffLdSym64 struct {
-	Lvalue  uint64 // Address field
-	Loffset uint32 // Byte offset into string table of symbol name
-	Lscnum  int16  // Section number containing symbol
-	Lsmtype int8   // Symbol type, export, import flags
-	Lsmclas int8   // Symbol storage class
-	Lifile  int32  // Import file ID; ordinal of import file IDs
-	Lparm   uint32 // Parameter type-check field
-}
-
-type xcoffLoaderSymbol struct {
-	sym    *sym.Symbol
-	smtype int8
-	smclas int8
-}
-
-type XcoffLdImportFile64 struct {
-	Limpidpath string
-	Limpidbase string
-	Limpidmem  string
-}
-
-type XcoffLdRel64 struct {
-	Lvaddr  uint64 // Address Field
-	Lrtype  uint16 // Relocation Size and Type
-	Lrsecnm int16  // Section Number being relocated
-	Lsymndx int32  // Loader-Section symbol table index
-}
-
-// xcoffLoaderReloc holds information about a relocation made by the loader.
-type xcoffLoaderReloc struct {
-	sym    *sym.Symbol
-	rel    *sym.Reloc
-	rtype  uint16
-	symndx int32
-}
-
-const (
-	XCOFF_R_POS = 0x00 // A(sym) Positive Relocation
-	XCOFF_R_NEG = 0x01 // -A(sym) Negative Relocation
-	XCOFF_R_REL = 0x02 // A(sym-*) Relative to self
-	XCOFF_R_TOC = 0x03 // A(sym-TOC) Relative to TOC
-	XCOFF_R_TRL = 0x12 // A(sym-TOC) TOC Relative indirect load.
-
-	XCOFF_R_TRLA = 0x13 // A(sym-TOC) TOC Rel load address. modifiable inst
-	XCOFF_R_GL   = 0x05 // A(external TOC of sym) Global Linkage
-	XCOFF_R_TCL  = 0x06 // A(local TOC of sym) Local object TOC address
-	XCOFF_R_RL   = 0x0C // A(sym) Pos indirect load. modifiable instruction
-	XCOFF_R_RLA  = 0x0D // A(sym) Pos Load Address. modifiable instruction
-	XCOFF_R_REF  = 0x0F // AL0(sym) Non relocating ref. No garbage collect
-	XCOFF_R_BA   = 0x08 // A(sym) Branch absolute. Cannot modify instruction
-	XCOFF_R_RBA  = 0x18 // A(sym) Branch absolute. modifiable instruction
-	XCOFF_R_BR   = 0x0A // A(sym-*) Branch rel to self. non modifiable
-	XCOFF_R_RBR  = 0x1A // A(sym-*) Branch rel to self. modifiable instr
-
-	XCOFF_R_TLS    = 0x20 // General-dynamic reference to TLS symbol
-	XCOFF_R_TLS_IE = 0x21 // Initial-exec reference to TLS symbol
-	XCOFF_R_TLS_LD = 0x22 // Local-dynamic reference to TLS symbol
-	XCOFF_R_TLS_LE = 0x23 // Local-exec reference to TLS symbol
-	XCOFF_R_TLSM   = 0x24 // Module reference to TLS symbol
-	XCOFF_R_TLSML  = 0x25 // Module reference to local (own) module
-
-	XCOFF_R_TOCU = 0x30 // Relative to TOC - high order bits
-	XCOFF_R_TOCL = 0x31 // Relative to TOC - low order bits
-)
-
-type XcoffLdStr64 struct {
-	size uint16
-	name string
-}
-
-// xcoffFile is used to build XCOFF file.
-type xcoffFile struct {
-	xfhdr           XcoffFileHdr64
-	xahdr           XcoffAoutHdr64
-	sections        []*XcoffScnHdr64
-	sectText        *XcoffScnHdr64
-	sectData        *XcoffScnHdr64
-	sectBss         *XcoffScnHdr64
-	stringTable     xcoffStringTable
-	sectNameToScnum map[string]int16
-	loaderSize      uint64
-	symtabOffset    int64                // offset to the start of symbol table
-	symbolCount     uint32               // number of symbol table records written
-	symtabSym       []xcoffSym           // XCOFF symbols for the symbol table
-	dynLibraries    map[string]int       // Dynamic libraries in .loader section. The integer represents its import file number (- 1)
-	loaderSymbols   []*xcoffLoaderSymbol // symbols inside .loader symbol table
-	loaderReloc     []*xcoffLoaderReloc  // Reloc that must be made inside loader
-}
-
-// Var used by XCOFF Generation algorithms
-var (
-	xfile xcoffFile
-)
-
-// xcoffStringTable is a XCOFF string table.
-type xcoffStringTable struct {
-	strings    []string
-	stringsLen int
-}
-
-// size returns size of string table t.
-func (t *xcoffStringTable) size() int {
-	// string table starts with 4-byte length at the beginning
-	return t.stringsLen + 4
-}
-
-// add adds string str to string table t.
-func (t *xcoffStringTable) add(str string) int {
-	off := t.size()
-	t.strings = append(t.strings, str)
-	t.stringsLen += len(str) + 1 // each string will have 0 appended to it
-	return off
-}
-
-// write writes string table t into the output file.
-func (t *xcoffStringTable) write(out *OutBuf) {
-	out.Write32(uint32(t.size()))
-	for _, s := range t.strings {
-		out.WriteString(s)
-		out.Write8(0)
-	}
-}
-
-// write writes XCOFF section sect into the output file.
-func (sect *XcoffScnHdr64) write(ctxt *Link) {
-	binary.Write(ctxt.Out, binary.BigEndian, sect)
-	ctxt.Out.Write32(0) // Add 4 empty bytes at the end to match alignment
-}
-
-// addSection adds section to the XCOFF file f.
-func (f *xcoffFile) addSection(name string, addr uint64, size uint64, fileoff uint64, flags uint32) *XcoffScnHdr64 {
-	sect := &XcoffScnHdr64{
-		Spaddr:  addr,
-		Svaddr:  addr,
-		Ssize:   size,
-		Sscnptr: fileoff,
-		Sflags:  flags,
-	}
-	copy(sect.Sname[:], name) // copy string to [8]byte
-	f.sections = append(f.sections, sect)
-	f.sectNameToScnum[name] = int16(len(f.sections))
-	return sect
-}
-
-// addDwarfSection adds a dwarf section to the XCOFF file f.
-// This function is similar to addSection, but Dwarf section names
-// must be modified to conventional names and they are various subtypes.
-func (f *xcoffFile) addDwarfSection(s *sym.Section) *XcoffScnHdr64 {
-	newName, subtype := xcoffGetDwarfSubtype(s.Name)
-	return f.addSection(newName, 0, s.Length, s.Seg.Fileoff+s.Vaddr-s.Seg.Vaddr, STYP_DWARF|subtype)
-}
-
-// xcoffGetDwarfSubtype returns the XCOFF name of the DWARF section str
-// and its subtype constant.
-func xcoffGetDwarfSubtype(str string) (string, uint32) {
-	switch str {
-	default:
-		Exitf("unknown DWARF section name for XCOFF: %s", str)
-	case ".debug_abbrev":
-		return ".dwabrev", SSUBTYP_DWABREV
-	case ".debug_info":
-		return ".dwinfo", SSUBTYP_DWINFO
-	case ".debug_frame":
-		return ".dwframe", SSUBTYP_DWFRAME
-	case ".debug_line":
-		return ".dwline", SSUBTYP_DWLINE
-	case ".debug_loc":
-		return ".dwloc", SSUBTYP_DWLOC
-	case ".debug_pubnames":
-		return ".dwpbnms", SSUBTYP_DWPBNMS
-	case ".debug_pubtypes":
-		return ".dwpbtyp", SSUBTYP_DWPBTYP
-	case ".debug_ranges":
-		return ".dwrnges", SSUBTYP_DWRNGES
-	}
-	// never used
-	return "", 0
-}
-
-// getXCOFFscnum returns the XCOFF section number of a Go section.
-func (f *xcoffFile) getXCOFFscnum(sect *sym.Section) int16 {
-	switch sect.Seg {
-	case &Segtext:
-		return f.sectNameToScnum[".text"]
-	case &Segdata:
-		if sect.Name == ".noptrbss" || sect.Name == ".bss" {
-			return f.sectNameToScnum[".bss"]
-		}
-		if sect.Name == ".tbss" {
-			return f.sectNameToScnum[".tbss"]
-		}
-		return f.sectNameToScnum[".data"]
-	case &Segdwarf:
-		name, _ := xcoffGetDwarfSubtype(sect.Name)
-		return f.sectNameToScnum[name]
-	case &Segrelrodata:
-		return f.sectNameToScnum[".data"]
-	}
-	Errorf(nil, "getXCOFFscnum not implemented for section %s", sect.Name)
-	return -1
-}
-
-// Xcoffinit initialised some internal value and setups
-// already known header information
-func Xcoffinit(ctxt *Link) {
-	xfile.dynLibraries = make(map[string]int)
-
-	HEADR = int32(Rnd(XCOFFHDRRESERVE, XCOFFSECTALIGN))
-	if *FlagTextAddr != -1 {
-		Errorf(nil, "-T not available on AIX")
-	}
-	*FlagTextAddr = XCOFFTEXTBASE + int64(HEADR)
-	if *FlagRound != -1 {
-		Errorf(nil, "-R not available on AIX")
-	}
-	*FlagRound = int(XCOFFSECTALIGN)
-
-}
-
-// SYMBOL TABLE
-
-// type records C_FILE information needed for genasmsym in XCOFF.
-type xcoffSymSrcFile struct {
-	name       string
-	file       *XcoffSymEnt64   // Symbol of this C_FILE
-	csectAux   *XcoffAuxCSect64 // Symbol for the current .csect
-	csectSymNb uint64           // Symbol number for the current .csect
-	csectSize  int64
-}
-
-var (
-	currDwscnoff   = make(map[string]uint64) // Needed to create C_DWARF symbols
-	currSymSrcFile xcoffSymSrcFile
-	outerSymSize   = make(map[string]int64)
-)
-
-// xcoffUpdateOuterSize stores the size of outer symbols in order to have it
-// in the symbol table.
-func xcoffUpdateOuterSize(ctxt *Link, size int64, stype sym.SymKind) {
-	if size == 0 {
-		return
-	}
-
-	switch stype {
-	default:
-		Errorf(nil, "unknown XCOFF outer symbol for type %s", stype.String())
-	case sym.SRODATA, sym.SRODATARELRO, sym.SFUNCTAB, sym.SSTRING:
-		// Nothing to do
-	case sym.STYPERELRO:
-		if ctxt.UseRelro() && (ctxt.BuildMode == BuildModeCArchive || ctxt.BuildMode == BuildModeCShared || ctxt.BuildMode == BuildModePIE) {
-			// runtime.types size must be removed, as it's a real symbol.
-			outerSymSize["typerel.*"] = size - ctxt.Syms.ROLookup("runtime.types", 0).Size
-			return
-		}
-		fallthrough
-	case sym.STYPE:
-		if !ctxt.DynlinkingGo() {
-			// runtime.types size must be removed, as it's a real symbol.
-			outerSymSize["type.*"] = size - ctxt.Syms.ROLookup("runtime.types", 0).Size
-		}
-	case sym.SGOSTRING:
-		outerSymSize["go.string.*"] = size
-	case sym.SGOFUNC:
-		if !ctxt.DynlinkingGo() {
-			outerSymSize["go.func.*"] = size
-		}
-	case sym.SGOFUNCRELRO:
-		outerSymSize["go.funcrel.*"] = size
-	case sym.SGCBITS:
-		outerSymSize["runtime.gcbits.*"] = size
-	case sym.SITABLINK:
-		outerSymSize["runtime.itablink"] = size
-
-	}
-
-}
-
-// addSymbol writes a symbol or an auxiliary symbol entry on ctxt.out.
-func (f *xcoffFile) addSymbol(sym xcoffSym) {
-	f.symtabSym = append(f.symtabSym, sym)
-	f.symbolCount++
-}
-
-// xcoffAlign returns the log base 2 of the symbol's alignment.
-func xcoffAlign(x *sym.Symbol, t SymbolType) uint8 {
-	align := x.Align
-	if align == 0 {
-		if t == TextSym {
-			align = int32(Funcalign)
-		} else {
-			align = symalign(x)
-		}
-	}
-	return logBase2(int(align))
-}
-
-// logBase2 returns the log in base 2 of a.
-func logBase2(a int) uint8 {
-	return uint8(bits.Len(uint(a)) - 1)
-}
-
-// Write symbols needed when a new file appeared:
-// - a C_FILE with one auxiliary entry for its name
-// - C_DWARF symbols to provide debug information
-// - a C_HIDEXT which will be a csect containing all of its functions
-// It needs several parameters to create .csect symbols such as its entry point and its section number.
-//
-// Currently, a new file is in fact a new package. It seems to be OK, but it might change
-// in the future.
-func (f *xcoffFile) writeSymbolNewFile(ctxt *Link, name string, firstEntry uint64, extnum int16) {
-	/* C_FILE */
-	s := &XcoffSymEnt64{
-		Noffset: uint32(f.stringTable.add(".file")),
-		Nsclass: C_FILE,
-		Nscnum:  N_DEBUG,
-		Ntype:   0, // Go isn't inside predefined language.
-		Nnumaux: 1,
-	}
-	f.addSymbol(s)
-	currSymSrcFile.file = s
-
-	// Auxiliary entry for file name.
-	auxf := &XcoffAuxFile64{
-		Xoffset:  uint32(f.stringTable.add(name)),
-		Xftype:   XFT_FN,
-		Xauxtype: _AUX_FILE,
-	}
-	f.addSymbol(auxf)
-
-	/* Dwarf */
-	for _, sect := range Segdwarf.Sections {
-		var dwsize uint64
-		if ctxt.LinkMode == LinkInternal {
-			// Find the size of this corresponding package DWARF compilation unit.
-			// This size is set during DWARF generation (see dwarf.go).
-			dwsize = getDwsectCUSize(sect.Name, name)
-			// .debug_abbrev is common to all packages and not found with the previous function
-			if sect.Name == ".debug_abbrev" {
-				s := ctxt.Syms.ROLookup(sect.Name, 0)
-				dwsize = uint64(s.Size)
-
-			}
-		} else {
-			// There is only one .FILE with external linking.
-			dwsize = sect.Length
-		}
-
-		// get XCOFF name
-		name, _ := xcoffGetDwarfSubtype(sect.Name)
-		s := &XcoffSymEnt64{
-			Nvalue:  currDwscnoff[sect.Name],
-			Noffset: uint32(f.stringTable.add(name)),
-			Nsclass: C_DWARF,
-			Nscnum:  f.getXCOFFscnum(sect),
-			Nnumaux: 1,
-		}
-
-		if currSymSrcFile.csectAux == nil {
-			// Dwarf relocations need the symbol number of .dw* symbols.
-			// It doesn't need to know it for each package, one is enough.
-			// currSymSrcFile.csectAux == nil means first package.
-			dws := ctxt.Syms.Lookup(sect.Name, 0)
-			dws.Dynid = int32(f.symbolCount)
-
-			if sect.Name == ".debug_frame" && ctxt.LinkMode != LinkExternal {
-				// CIE size must be added to the first package.
-				dwsize += 48
-			}
-		}
-
-		f.addSymbol(s)
-
-		// update the DWARF section offset in this file
-		if sect.Name != ".debug_abbrev" {
-			currDwscnoff[sect.Name] += dwsize
-		}
-
-		// Auxiliary dwarf section
-		auxd := &XcoffAuxDWARF64{
-			Xscnlen:  dwsize,
-			Xauxtype: _AUX_SECT,
-		}
-
-		f.addSymbol(auxd)
-	}
-
-	/* .csect */
-	// Check if extnum is in text.
-	// This is temporary and only here to check if this algorithm is correct.
-	if extnum != 1 {
-		Exitf("XCOFF symtab: A new file was detected with its first symbol not in .text")
-	}
-
-	currSymSrcFile.csectSymNb = uint64(f.symbolCount)
-
-	// No offset because no name
-	s = &XcoffSymEnt64{
-		Nvalue:  firstEntry,
-		Nscnum:  extnum,
-		Nsclass: C_HIDEXT,
-		Ntype:   0, // check visibility ?
-		Nnumaux: 1,
-	}
-	f.addSymbol(s)
-
-	aux := &XcoffAuxCSect64{
-		Xsmclas:  XMC_PR,
-		Xsmtyp:   XTY_SD | logBase2(Funcalign)<<3,
-		Xauxtype: _AUX_CSECT,
-	}
-	f.addSymbol(aux)
-
-	currSymSrcFile.csectAux = aux
-	currSymSrcFile.csectSize = 0
-}
-
-// Update values for the previous package.
-//  - Svalue of the C_FILE symbol: if it is the last one, this Svalue must be -1
-//  - Xsclen of the csect symbol.
-func (f *xcoffFile) updatePreviousFile(ctxt *Link, last bool) {
-	// first file
-	if currSymSrcFile.file == nil {
-		return
-	}
-
-	// Update C_FILE
-	cfile := currSymSrcFile.file
-	if last {
-		cfile.Nvalue = 0xFFFFFFFFFFFFFFFF
-	} else {
-		cfile.Nvalue = uint64(f.symbolCount)
-	}
-
-	// update csect scnlen in this auxiliary entry
-	aux := currSymSrcFile.csectAux
-	aux.Xscnlenlo = uint32(currSymSrcFile.csectSize & 0xFFFFFFFF)
-	aux.Xscnlenhi = uint32(currSymSrcFile.csectSize >> 32)
-}
-
-// Write symbol representing a .text function.
-// The symbol table is split with C_FILE corresponding to each package
-// and not to each source file as it should be.
-func (f *xcoffFile) writeSymbolFunc(ctxt *Link, x *sym.Symbol) []xcoffSym {
-	// New XCOFF symbols which will be written.
-	syms := []xcoffSym{}
-
-	// Check if a new file is detected.
-	if strings.Contains(x.Name, "-tramp") || strings.HasPrefix(x.Name, "runtime.text.") {
-		// Trampoline don't have a FILE so there are considered
-		// in the current file.
-		// Same goes for runtime.text.X symbols.
-	} else if x.File == "" { // Undefined global symbol
-		// If this happens, the algorithm must be redone.
-		if currSymSrcFile.name != "" {
-			Exitf("undefined global symbol found inside another file")
-		}
-	} else {
-		// Current file has changed. New C_FILE, C_DWARF, etc must be generated.
-		if currSymSrcFile.name != x.File {
-			if ctxt.LinkMode == LinkInternal {
-				// update previous file values
-				xfile.updatePreviousFile(ctxt, false)
-				currSymSrcFile.name = x.File
-				f.writeSymbolNewFile(ctxt, x.File, uint64(x.Value), xfile.getXCOFFscnum(x.Sect))
-			} else {
-				// With external linking, ld will crash if there is several
-				// .FILE and DWARF debugging enable, somewhere during
-				// the relocation phase.
-				// Therefore, all packages are merged under a fake .FILE
-				// "go_functions".
-				// TODO(aix); remove once ld has been fixed or the triggering
-				// relocation has been found and fixed.
-				if currSymSrcFile.name == "" {
-					currSymSrcFile.name = x.File
-					f.writeSymbolNewFile(ctxt, "go_functions", uint64(x.Value), xfile.getXCOFFscnum(x.Sect))
-				}
-			}
-
-		}
-	}
-
-	s := &XcoffSymEnt64{
-		Nsclass: C_EXT,
-		Noffset: uint32(xfile.stringTable.add(x.Extname())),
-		Nvalue:  uint64(x.Value),
-		Nscnum:  f.getXCOFFscnum(x.Sect),
-		Ntype:   SYM_TYPE_FUNC,
-		Nnumaux: 2,
-	}
-
-	if x.Version != 0 || x.Attr.VisibilityHidden() || x.Attr.Local() {
-		s.Nsclass = C_HIDEXT
-	}
-
-	x.Dynid = int32(xfile.symbolCount)
-	syms = append(syms, s)
-
-	// Update current csect size
-	currSymSrcFile.csectSize += x.Size
-
-	// create auxiliary entries
-	a2 := &XcoffAuxFcn64{
-		Xfsize:   uint32(x.Size),
-		Xlnnoptr: 0,                     // TODO
-		Xendndx:  xfile.symbolCount + 3, // this symbol + 2 aux entries
-		Xauxtype: _AUX_FCN,
-	}
-	syms = append(syms, a2)
-
-	a4 := &XcoffAuxCSect64{
-		Xscnlenlo: uint32(currSymSrcFile.csectSymNb & 0xFFFFFFFF),
-		Xscnlenhi: uint32(currSymSrcFile.csectSymNb >> 32),
-		Xsmclas:   XMC_PR, // Program Code
-		Xsmtyp:    XTY_LD, // label definition (based on C)
-		Xauxtype:  _AUX_CSECT,
-	}
-	a4.Xsmtyp |= uint8(xcoffAlign(x, TextSym) << 3)
-
-	syms = append(syms, a4)
-	return syms
-}
-
-// put function used by genasmsym to write symbol table
-func putaixsym(ctxt *Link, x *sym.Symbol, str string, t SymbolType, addr int64, go_ *sym.Symbol) {
-
-	// All XCOFF symbols generated by this GO symbols
-	// Can be a symbol entry or a auxiliary entry
-	syms := []xcoffSym{}
-
-	switch t {
-	default:
-		return
-
-	case TextSym:
-		if x.FuncInfo != nil || strings.Contains(x.Name, "-tramp") || strings.HasPrefix(x.Name, "runtime.text.") {
-			// Function within a file
-			syms = xfile.writeSymbolFunc(ctxt, x)
-		} else {
-			// Only runtime.text and runtime.etext come through this way
-			if x.Name != "runtime.text" && x.Name != "runtime.etext" && x.Name != "go.buildid" {
-				Exitf("putaixsym: unknown text symbol %s", x.Name)
-			}
-			s := &XcoffSymEnt64{
-				Nsclass: C_HIDEXT,
-				Noffset: uint32(xfile.stringTable.add(str)),
-				Nvalue:  uint64(x.Value),
-				Nscnum:  xfile.getXCOFFscnum(x.Sect),
-				Ntype:   SYM_TYPE_FUNC,
-				Nnumaux: 1,
-			}
-			x.Dynid = int32(xfile.symbolCount)
-			syms = append(syms, s)
-
-			size := uint64(x.Size)
-			a4 := &XcoffAuxCSect64{
-				Xauxtype:  _AUX_CSECT,
-				Xscnlenlo: uint32(size & 0xFFFFFFFF),
-				Xscnlenhi: uint32(size >> 32),
-				Xsmclas:   XMC_PR,
-				Xsmtyp:    XTY_SD,
-			}
-			a4.Xsmtyp |= uint8(xcoffAlign(x, TextSym) << 3)
-			syms = append(syms, a4)
-
-		}
-
-	case DataSym, BSSSym:
-		s := &XcoffSymEnt64{
-			Nsclass: C_EXT,
-			Noffset: uint32(xfile.stringTable.add(str)),
-			Nvalue:  uint64(x.Value),
-			Nscnum:  xfile.getXCOFFscnum(x.Sect),
-			Nnumaux: 1,
-		}
-
-		if x.Version != 0 || x.Attr.VisibilityHidden() || x.Attr.Local() {
-			// There is more symbols in the case of a global data
-			// which are related to the assembly generated
-			// to access such symbols.
-			// But as Golang as its own way to check if a symbol is
-			// global or local (the capital letter), we don't need to
-			// implement them yet.
-			s.Nsclass = C_HIDEXT
-		}
-
-		x.Dynid = int32(xfile.symbolCount)
-		syms = append(syms, s)
-
-		// Create auxiliary entry
-
-		// Normally, size should be the size of csect containing all
-		// the data and bss symbols of one file/package.
-		// However, it's easier to just have a csect for each symbol.
-		// It might change
-		size := uint64(x.Size)
-		a4 := &XcoffAuxCSect64{
-			Xauxtype:  _AUX_CSECT,
-			Xscnlenlo: uint32(size & 0xFFFFFFFF),
-			Xscnlenhi: uint32(size >> 32),
-		}
-
-		if x.Type >= sym.STYPE && x.Type <= sym.SPCLNTAB {
-			if ctxt.LinkMode == LinkExternal && strings.HasPrefix(x.Sect.Name, ".data.rel.ro") {
-				// During external linking, read-only datas with relocation
-				// must be in .data.
-				a4.Xsmclas = XMC_RW
-			} else {
-				// Read only data
-				a4.Xsmclas = XMC_RO
-			}
-		} else if x.Type == sym.SDATA && strings.HasPrefix(x.Name, "TOC.") && ctxt.LinkMode == LinkExternal {
-			a4.Xsmclas = XMC_TC
-		} else if x.Name == "TOC" {
-			a4.Xsmclas = XMC_TC0
-		} else {
-			a4.Xsmclas = XMC_RW
-		}
-		if t == DataSym {
-			a4.Xsmtyp |= XTY_SD
-		} else {
-			a4.Xsmtyp |= XTY_CM
-		}
-
-		a4.Xsmtyp |= uint8(xcoffAlign(x, t) << 3)
-
-		syms = append(syms, a4)
-
-	case UndefinedSym:
-		if x.Type != sym.SDYNIMPORT && x.Type != sym.SHOSTOBJ && x.Type != sym.SUNDEFEXT {
-			return
-		}
-		s := &XcoffSymEnt64{
-			Nsclass: C_EXT,
-			Noffset: uint32(xfile.stringTable.add(str)),
-			Nnumaux: 1,
-		}
-		x.Dynid = int32(xfile.symbolCount)
-		syms = append(syms, s)
-
-		a4 := &XcoffAuxCSect64{
-			Xauxtype: _AUX_CSECT,
-			Xsmclas:  XMC_DS,
-			Xsmtyp:   XTY_ER | XTY_IMP,
-		}
-
-		if x.Name == "__n_pthreads" {
-			// Currently, all imported symbols made by cgo_import_dynamic are
-			// syscall functions, except __n_pthreads which is a variable.
-			// TODO(aix): Find a way to detect variables imported by cgo.
-			a4.Xsmclas = XMC_RW
-		}
-
-		syms = append(syms, a4)
-
-	case TLSSym:
-		s := &XcoffSymEnt64{
-			Nsclass: C_EXT,
-			Noffset: uint32(xfile.stringTable.add(str)),
-			Nscnum:  xfile.getXCOFFscnum(x.Sect),
-			Nvalue:  uint64(x.Value),
-			Nnumaux: 1,
-		}
-
-		x.Dynid = int32(xfile.symbolCount)
-		syms = append(syms, s)
-
-		size := uint64(x.Size)
-		a4 := &XcoffAuxCSect64{
-			Xauxtype:  _AUX_CSECT,
-			Xsmclas:   XMC_UL,
-			Xsmtyp:    XTY_CM,
-			Xscnlenlo: uint32(size & 0xFFFFFFFF),
-			Xscnlenhi: uint32(size >> 32),
-		}
-
-		syms = append(syms, a4)
-	}
-
-	for _, s := range syms {
-		xfile.addSymbol(s)
-	}
-}
-
-// Generate XCOFF Symbol table.
-// It will be written in out file in Asmbxcoff, because it must be
-// at the very end, especially after relocation sections which needs symbols' index.
-func (f *xcoffFile) asmaixsym(ctxt *Link) {
-	// Get correct size for symbols wrapping others symbols like go.string.*
-	// sym.Size can be used directly as the symbols have already been written.
-	for name, size := range outerSymSize {
-		sym := ctxt.Syms.ROLookup(name, 0)
-		if sym == nil {
-			Errorf(nil, "unknown outer symbol with name %s", name)
-		} else {
-			sym.Size = size
-		}
-	}
-
-	genasmsym(ctxt, putaixsym)
-	xfile.updatePreviousFile(ctxt, true)
-}
-
-func (f *xcoffFile) genDynSym(ctxt *Link) {
-	var dynsyms []*sym.Symbol
-	for _, s := range ctxt.Syms.Allsym {
-		if s.Type != sym.SHOSTOBJ && s.Type != sym.SDYNIMPORT {
-			continue
-		}
-		dynsyms = append(dynsyms, s)
-	}
-
-	for _, s := range dynsyms {
-		f.adddynimpsym(ctxt, s)
-
-		if _, ok := f.dynLibraries[s.Dynimplib()]; !ok {
-			f.dynLibraries[s.Dynimplib()] = len(f.dynLibraries)
-		}
-
-	}
-
-}
-
-// (*xcoffFile)adddynimpsym adds the dynamic symbol "s" to a XCOFF file.
-// A new symbol named s.Extname() is created to be the actual dynamic symbol
-// in the .loader section and in the symbol table as an External Reference.
-// The symbol "s" is transformed to SXCOFFTOC to end up in .data section.
-// However, there is no writing protection on those symbols and
-// it might need to be added.
-// TODO(aix): Handles dynamic symbols without library.
-func (f *xcoffFile) adddynimpsym(ctxt *Link, s *sym.Symbol) {
-	// Check that library name is given.
-	// Pattern is already checked when compiling.
-	if ctxt.LinkMode == LinkInternal && s.Dynimplib() == "" {
-		Errorf(s, "imported symbol must have a given library")
-	}
-
-	s.Type = sym.SXCOFFTOC
-
-	// Create new dynamic symbol
-	extsym := ctxt.Syms.Lookup(s.Extname(), 0)
-	extsym.Type = sym.SDYNIMPORT
-	extsym.Attr |= sym.AttrReachable
-	extsym.SetDynimplib(s.Dynimplib())
-	extsym.SetExtname(s.Extname())
-	extsym.SetDynimpvers(s.Dynimpvers())
-
-	// Add loader symbol
-	lds := &xcoffLoaderSymbol{
-		sym:    extsym,
-		smtype: XTY_IMP,
-		smclas: XMC_DS,
-	}
-	if s.Name == "__n_pthreads" {
-		// Currently, all imported symbols made by cgo_import_dynamic are
-		// syscall functions, except __n_pthreads which is a variable.
-		// TODO(aix): Find a way to detect variables imported by cgo.
-		lds.smclas = XMC_RW
-	}
-	f.loaderSymbols = append(f.loaderSymbols, lds)
-
-	// Relocation to retrieve the external address
-	s.AddBytes(make([]byte, 8))
-	s.SetAddr(ctxt.Arch, 0, extsym)
-
-}
-
-// 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 {
-		return true
-	}
-	if s.Type <= sym.SPCLNTAB {
-		Errorf(s, "cannot have a relocation to %s in a text section symbol", r.Sym.Name)
-		return false
-	}
-
-	ldr := &xcoffLoaderReloc{
-		sym: s,
-		rel: r,
-	}
-
-	switch r.Type {
-	default:
-		Errorf(s, "unexpected .loader relocation to symbol: %s (type: %s)", r.Sym.Name, r.Type.String())
-		return false
-	case objabi.R_ADDR:
-		if s.Type == sym.SXCOFFTOC && r.Sym.Type == sym.SDYNIMPORT {
-			// Imported symbol relocation
-			for i, dynsym := range xfile.loaderSymbols {
-				if dynsym.sym.Name == r.Sym.Name {
-					ldr.symndx = int32(i + 3) // +3 because of 3 section symbols
-					break
-				}
-			}
-		} else if s.Type == sym.SDATA {
-			switch r.Sym.Sect.Seg {
-			default:
-				Errorf(s, "unknown segment for .loader relocation with symbol %s", r.Sym.Name)
-			case &Segtext:
-			case &Segrodata:
-				ldr.symndx = 0 // .text
-			case &Segdata:
-				if r.Sym.Type == sym.SBSS || r.Sym.Type == sym.SNOPTRBSS {
-					ldr.symndx = 2 // .bss
-				} else {
-					ldr.symndx = 1 // .data
-				}
-
-			}
-
-		} else {
-			Errorf(s, "unexpected type for .loader relocation R_ADDR for symbol %s: %s to %s", r.Sym.Name, s.Type, r.Sym.Type)
-			return false
-		}
-
-		ldr.rtype = 0x3F<<8 + XCOFF_R_POS
-	}
-
-	xfile.loaderReloc = append(xfile.loaderReloc, ldr)
-	return true
-}
-
-func (ctxt *Link) doxcoff() {
-	if *FlagD {
-		// All XCOFF files have dynamic symbols because of the syscalls.
-		Exitf("-d is not available on AIX")
-	}
-
-	// TOC
-	toc := ctxt.Syms.Lookup("TOC", 0)
-	toc.Type = sym.SXCOFFTOC
-	toc.Attr |= sym.AttrReachable
-	toc.Attr |= sym.AttrVisibilityHidden
-
-	// Add entry point to .loader symbols.
-	ep := ctxt.Syms.ROLookup(*flagEntrySymbol, 0)
-	if !ep.Attr.Reachable() {
-		Exitf("wrong entry point")
-	}
-
-	xfile.loaderSymbols = append(xfile.loaderSymbols, &xcoffLoaderSymbol{
-		sym:    ep,
-		smtype: XTY_ENT | XTY_SD,
-		smclas: XMC_DS,
-	})
-
-	xfile.genDynSym(ctxt)
-
-	for _, s := range ctxt.Syms.Allsym {
-		if strings.HasPrefix(s.Name, "TOC.") {
-			s.Type = sym.SXCOFFTOC
-		}
-	}
-
-	if ctxt.LinkMode == LinkExternal {
-		// Change rt0_go name to match name in runtime/cgo:main().
-		rt0 := ctxt.Syms.ROLookup("runtime.rt0_go", 0)
-		ctxt.Syms.Rename(rt0.Name, "runtime_rt0_go", 0, ctxt.Reachparent)
-
-		for _, s := range ctxt.Syms.Allsym {
-			if !s.Attr.CgoExport() {
-				continue
-			}
-
-			name := s.Extname()
-			if s.Type == sym.STEXT {
-				// On AIX, a exported function must have two symbols:
-				// - a .text symbol which must start with a ".".
-				// - a .data symbol which is a function descriptor.
-				ctxt.Syms.Rename(s.Name, "."+name, 0, ctxt.Reachparent)
-
-				desc := ctxt.Syms.Lookup(name, 0)
-				desc.Type = sym.SNOPTRDATA
-				desc.AddAddr(ctxt.Arch, s)
-				desc.AddAddr(ctxt.Arch, toc)
-				desc.AddUint64(ctxt.Arch, 0)
-			}
-		}
-	}
-}
-
-// Loader section
-// Currently, this section is created from scratch when assembling the XCOFF file
-// according to information retrieved in xfile object.
-
-// Create loader section and returns its size
-func Loaderblk(ctxt *Link, off uint64) {
-	xfile.writeLdrScn(ctxt, off)
-}
-
-func (f *xcoffFile) writeLdrScn(ctxt *Link, globalOff uint64) {
-	var symtab []*XcoffLdSym64
-	var strtab []*XcoffLdStr64
-	var importtab []*XcoffLdImportFile64
-	var reloctab []*XcoffLdRel64
-	var dynimpreloc []*XcoffLdRel64
-
-	// As the string table is updated in any loader subsection,
-	//  its length must be computed at the same time.
-	stlen := uint32(0)
-
-	// Loader Header
-	hdr := &XcoffLdHdr64{
-		Lversion: 2,
-		Lsymoff:  LDHDRSZ_64,
-	}
-
-	/* Symbol table */
-	for _, s := range f.loaderSymbols {
-		lds := &XcoffLdSym64{
-			Loffset: uint32(stlen + 2),
-			Lsmtype: s.smtype,
-			Lsmclas: s.smclas,
-		}
-		switch s.smtype {
-		default:
-			Errorf(s.sym, "unexpected loader symbol type: 0x%x", s.smtype)
-		case XTY_ENT | XTY_SD:
-			lds.Lvalue = uint64(s.sym.Value)
-			lds.Lscnum = f.getXCOFFscnum(s.sym.Sect)
-		case XTY_IMP:
-			lds.Lifile = int32(f.dynLibraries[s.sym.Dynimplib()] + 1)
-		}
-		ldstr := &XcoffLdStr64{
-			size: uint16(len(s.sym.Name) + 1), // + null terminator
-			name: s.sym.Name,
-		}
-		stlen += uint32(2 + ldstr.size) // 2 = sizeof ldstr.size
-		symtab = append(symtab, lds)
-		strtab = append(strtab, ldstr)
-
-	}
-
-	hdr.Lnsyms = int32(len(symtab))
-	hdr.Lrldoff = hdr.Lsymoff + uint64(24*hdr.Lnsyms) // 24 = sizeof one symbol
-	off := hdr.Lrldoff                                // current offset is the same of reloc offset
-
-	/* Reloc */
-	ep := ctxt.Syms.ROLookup(*flagEntrySymbol, 0)
-	ldr := &XcoffLdRel64{
-		Lvaddr:  uint64(ep.Value),
-		Lrtype:  0x3F00,
-		Lrsecnm: f.getXCOFFscnum(ep.Sect),
-		Lsymndx: 0,
-	}
-	off += 16
-	reloctab = append(reloctab, ldr)
-
-	off += uint64(16 * len(f.loaderReloc))
-	for _, r := range f.loaderReloc {
-		ldr = &XcoffLdRel64{
-			Lvaddr:  uint64(r.sym.Value + int64(r.rel.Off)),
-			Lrtype:  r.rtype,
-			Lsymndx: r.symndx,
-		}
-
-		if r.sym.Sect != nil {
-			ldr.Lrsecnm = f.getXCOFFscnum(r.sym.Sect)
-		}
-
-		reloctab = append(reloctab, ldr)
-	}
-
-	off += uint64(16 * len(dynimpreloc))
-	reloctab = append(reloctab, dynimpreloc...)
-
-	hdr.Lnreloc = int32(len(reloctab))
-	hdr.Limpoff = off
-
-	/* Import */
-	// Default import: /usr/lib:/lib
-	ldimpf := &XcoffLdImportFile64{
-		Limpidpath: "/usr/lib:/lib",
-	}
-	off += uint64(len(ldimpf.Limpidpath) + len(ldimpf.Limpidbase) + len(ldimpf.Limpidmem) + 3) // + null delimiter
-	importtab = append(importtab, ldimpf)
-
-	// The map created by adddynimpsym associates the name to a number
-	// This number represents the librairie index (- 1) in this import files section
-	// Therefore, they must be sorted before being put inside the section
-	libsOrdered := make([]string, len(f.dynLibraries))
-	for key, val := range f.dynLibraries {
-		if libsOrdered[val] != "" {
-			continue
-		}
-		libsOrdered[val] = key
-	}
-
-	for _, lib := range libsOrdered {
-		// lib string is defined as base.a/mem.o or path/base.a/mem.o
-		n := strings.Split(lib, "/")
-		path := ""
-		base := n[len(n)-2]
-		mem := n[len(n)-1]
-		if len(n) > 2 {
-			path = lib[:len(lib)-len(base)-len(mem)-2]
-
-		}
-		ldimpf = &XcoffLdImportFile64{
-			Limpidpath: path,
-			Limpidbase: base,
-			Limpidmem:  mem,
-		}
-		off += uint64(len(ldimpf.Limpidpath) + len(ldimpf.Limpidbase) + len(ldimpf.Limpidmem) + 3) // + null delimiter
-		importtab = append(importtab, ldimpf)
-	}
-
-	hdr.Lnimpid = int32(len(importtab))
-	hdr.Listlen = uint32(off - hdr.Limpoff)
-	hdr.Lstoff = off
-	hdr.Lstlen = stlen
-
-	/* Writing */
-	ctxt.Out.SeekSet(int64(globalOff))
-	binary.Write(ctxt.Out, ctxt.Arch.ByteOrder, hdr)
-
-	for _, s := range symtab {
-		binary.Write(ctxt.Out, ctxt.Arch.ByteOrder, s)
-
-	}
-	for _, r := range reloctab {
-		binary.Write(ctxt.Out, ctxt.Arch.ByteOrder, r)
-	}
-	for _, f := range importtab {
-		ctxt.Out.WriteString(f.Limpidpath)
-		ctxt.Out.Write8(0)
-		ctxt.Out.WriteString(f.Limpidbase)
-		ctxt.Out.Write8(0)
-		ctxt.Out.WriteString(f.Limpidmem)
-		ctxt.Out.Write8(0)
-	}
-	for _, s := range strtab {
-		ctxt.Out.Write16(s.size)
-		ctxt.Out.WriteString(s.name)
-		ctxt.Out.Write8(0) // null terminator
-	}
-
-	f.loaderSize = off + uint64(stlen)
-	ctxt.Out.Flush()
-
-	/* again for printing */
-	if !*flagA {
-		return
-	}
-
-	ctxt.Logf("\n.loader section")
-	// write in buf
-	var buf bytes.Buffer
-
-	binary.Write(&buf, ctxt.Arch.ByteOrder, hdr)
-	for _, s := range symtab {
-		binary.Write(&buf, ctxt.Arch.ByteOrder, s)
-
-	}
-	for _, f := range importtab {
-		buf.WriteString(f.Limpidpath)
-		buf.WriteByte(0)
-		buf.WriteString(f.Limpidbase)
-		buf.WriteByte(0)
-		buf.WriteString(f.Limpidmem)
-		buf.WriteByte(0)
-	}
-	for _, s := range strtab {
-		binary.Write(&buf, ctxt.Arch.ByteOrder, s.size)
-		buf.WriteString(s.name)
-		buf.WriteByte(0) // null terminator
-	}
-
-	// Log buffer
-	ctxt.Logf("\n\t%.8x|", globalOff)
-	for i, b := range buf.Bytes() {
-		if i > 0 && i%16 == 0 {
-			ctxt.Logf("\n\t%.8x|", uint64(globalOff)+uint64(i))
-		}
-		ctxt.Logf(" %.2x", b)
-	}
-	ctxt.Logf("\n")
-
-}
-
-// XCOFF assembling and writing file
-
-func (f *xcoffFile) writeFileHeader(ctxt *Link) {
-	// File header
-	f.xfhdr.Fmagic = U64_TOCMAGIC
-	f.xfhdr.Fnscns = uint16(len(f.sections))
-	f.xfhdr.Ftimedat = 0
-
-	if !*FlagS {
-		f.xfhdr.Fsymptr = uint64(f.symtabOffset)
-		f.xfhdr.Fnsyms = int32(f.symbolCount)
-	}
-
-	if ctxt.BuildMode == BuildModeExe && ctxt.LinkMode == LinkInternal {
-		f.xfhdr.Fopthdr = AOUTHSZ_EXEC64
-		f.xfhdr.Fflags = F_EXEC
-
-		// auxiliary header
-		f.xahdr.Ovstamp = 1 // based on dump -o
-		f.xahdr.Omagic = 0x10b
-		copy(f.xahdr.Omodtype[:], "1L")
-		entry := ctxt.Syms.ROLookup(*flagEntrySymbol, 0)
-		f.xahdr.Oentry = uint64(entry.Value)
-		f.xahdr.Osnentry = f.getXCOFFscnum(entry.Sect)
-		toc := ctxt.Syms.ROLookup("TOC", 0)
-		f.xahdr.Otoc = uint64(toc.Value)
-		f.xahdr.Osntoc = f.getXCOFFscnum(toc.Sect)
-
-		f.xahdr.Oalgntext = int16(logBase2(int(Funcalign)))
-		f.xahdr.Oalgndata = 0x5
-
-		binary.Write(ctxt.Out, binary.BigEndian, &f.xfhdr)
-		binary.Write(ctxt.Out, binary.BigEndian, &f.xahdr)
-	} else {
-		f.xfhdr.Fopthdr = 0
-		binary.Write(ctxt.Out, binary.BigEndian, &f.xfhdr)
-	}
-
-}
-
-func xcoffwrite(ctxt *Link) {
-	ctxt.Out.SeekSet(0)
-
-	xfile.writeFileHeader(ctxt)
-
-	for _, sect := range xfile.sections {
-		sect.write(ctxt)
-	}
-}
-
-// Generate XCOFF assembly file
-func Asmbxcoff(ctxt *Link, fileoff int64) {
-	xfile.sectNameToScnum = make(map[string]int16)
-
-	// Add sections
-	s := xfile.addSection(".text", Segtext.Vaddr, Segtext.Length, Segtext.Fileoff, STYP_TEXT)
-	xfile.xahdr.Otextstart = s.Svaddr
-	xfile.xahdr.Osntext = xfile.sectNameToScnum[".text"]
-	xfile.xahdr.Otsize = s.Ssize
-	xfile.sectText = s
-
-	segdataVaddr := Segdata.Vaddr
-	segdataFilelen := Segdata.Filelen
-	segdataFileoff := Segdata.Fileoff
-	segbssFilelen := Segdata.Length - Segdata.Filelen
-	if len(Segrelrodata.Sections) > 0 {
-		// Merge relro segment to data segment as
-		// relro data are inside data segment on AIX.
-		segdataVaddr = Segrelrodata.Vaddr
-		segdataFileoff = Segrelrodata.Fileoff
-		segdataFilelen = Segdata.Vaddr + Segdata.Filelen - Segrelrodata.Vaddr
-	}
-
-	s = xfile.addSection(".data", segdataVaddr, segdataFilelen, segdataFileoff, STYP_DATA)
-	xfile.xahdr.Odatastart = s.Svaddr
-	xfile.xahdr.Osndata = xfile.sectNameToScnum[".data"]
-	xfile.xahdr.Odsize = s.Ssize
-	xfile.sectData = s
-
-	s = xfile.addSection(".bss", segdataVaddr+segdataFilelen, segbssFilelen, 0, STYP_BSS)
-	xfile.xahdr.Osnbss = xfile.sectNameToScnum[".bss"]
-	xfile.xahdr.Obsize = s.Ssize
-	xfile.sectBss = s
-
-	if ctxt.LinkMode == LinkExternal {
-		var tbss *sym.Section
-		for _, s := range Segdata.Sections {
-			if s.Name == ".tbss" {
-				tbss = s
-				break
-			}
-		}
-		s = xfile.addSection(".tbss", tbss.Vaddr, tbss.Length, 0, STYP_TBSS)
-	}
-
-	// add dwarf sections
-	for _, sect := range Segdwarf.Sections {
-		xfile.addDwarfSection(sect)
-	}
-
-	// add and write remaining sections
-	if ctxt.LinkMode == LinkInternal {
-		// Loader section
-		if ctxt.BuildMode == BuildModeExe {
-			Loaderblk(ctxt, uint64(fileoff))
-			s = xfile.addSection(".loader", 0, xfile.loaderSize, uint64(fileoff), STYP_LOADER)
-			xfile.xahdr.Osnloader = xfile.sectNameToScnum[".loader"]
-
-			// Update fileoff for symbol table
-			fileoff += int64(xfile.loaderSize)
-		}
-	}
-
-	// Create Symbol table
-	xfile.asmaixsym(ctxt)
-
-	if ctxt.LinkMode == LinkExternal {
-		xfile.emitRelocations(ctxt, fileoff)
-	}
-
-	// Write Symbol table
-	xfile.symtabOffset = ctxt.Out.Offset()
-	for _, s := range xfile.symtabSym {
-		binary.Write(ctxt.Out, ctxt.Arch.ByteOrder, s)
-	}
-	// write string table
-	xfile.stringTable.write(ctxt.Out)
-
-	ctxt.Out.Flush()
-
-	// write headers
-	xcoffwrite(ctxt)
-}
-
-// byOffset is used to sort relocations by offset
-type byOffset []sym.Reloc
-
-func (x byOffset) Len() int { return len(x) }
-
-func (x byOffset) Swap(i, j int) {
-	x[i], x[j] = x[j], x[i]
-}
-
-func (x byOffset) Less(i, j int) bool {
-	return x[i].Off < x[j].Off
-}
-
-// emitRelocations emits relocation entries for go.o in external linking.
-func (f *xcoffFile) emitRelocations(ctxt *Link, fileoff int64) {
-	ctxt.Out.SeekSet(fileoff)
-	for ctxt.Out.Offset()&7 != 0 {
-		ctxt.Out.Write8(0)
-	}
-
-	// relocsect relocates symbols from first in section sect, and returns
-	// the total number of relocations emitted.
-	relocsect := func(sect *sym.Section, syms []*sym.Symbol, base uint64) uint32 {
-		// ctxt.Logf("%s 0x%x\n", sect.Name, sect.Vaddr)
-		// If main section has no bits, nothing to relocate.
-		if sect.Vaddr >= sect.Seg.Vaddr+sect.Seg.Filelen {
-			return 0
-		}
-		sect.Reloff = uint64(ctxt.Out.Offset())
-		for i, s := range syms {
-			if !s.Attr.Reachable() {
-				continue
-			}
-			if uint64(s.Value) >= sect.Vaddr {
-				syms = syms[i:]
-				break
-			}
-		}
-		eaddr := int64(sect.Vaddr + sect.Length)
-		for _, s := range syms {
-			if !s.Attr.Reachable() {
-				continue
-			}
-			if s.Value >= int64(eaddr) {
-				break
-			}
-
-			// Relocation must be ordered by address, so s.R is ordered by Off.
-			sort.Sort(byOffset(s.R))
-
-			for ri := range s.R {
-
-				r := &s.R[ri]
-
-				if r.Done {
-					continue
-				}
-				if r.Xsym == nil {
-					Errorf(s, "missing xsym in relocation")
-					continue
-				}
-				if r.Xsym.Dynid < 0 {
-					Errorf(s, "reloc %s to non-coff symbol %s (outer=%s) %d %d", r.Type.String(), r.Sym.Name, r.Xsym.Name, r.Sym.Type, r.Xsym.Dynid)
-				}
-				if !thearch.Xcoffreloc1(ctxt.Arch, ctxt.Out, s, r, int64(uint64(s.Value+int64(r.Off))-base)) {
-					Errorf(s, "unsupported obj reloc %d(%s)/%d to %s", r.Type, r.Type.String(), r.Siz, r.Sym.Name)
-				}
-			}
-		}
-		sect.Rellen = uint64(ctxt.Out.Offset()) - sect.Reloff
-		return uint32(sect.Rellen) / RELSZ_64
-	}
-	sects := []struct {
-		xcoffSect *XcoffScnHdr64
-		segs      []*sym.Segment
-	}{
-		{f.sectText, []*sym.Segment{&Segtext}},
-		{f.sectData, []*sym.Segment{&Segrelrodata, &Segdata}},
-	}
-	for _, s := range sects {
-		s.xcoffSect.Srelptr = uint64(ctxt.Out.Offset())
-		n := uint32(0)
-		for _, seg := range s.segs {
-			for _, sect := range seg.Sections {
-				if sect.Name == ".text" {
-					n += relocsect(sect, ctxt.Textp, 0)
-				} else {
-					n += relocsect(sect, datap, 0)
-				}
-			}
-		}
-		s.xcoffSect.Snreloc += n
-	}
-
-dwarfLoop:
-	for _, sect := range Segdwarf.Sections {
-		for _, xcoffSect := range f.sections {
-			_, subtyp := xcoffGetDwarfSubtype(sect.Name)
-			if xcoffSect.Sflags&0xF0000 == subtyp {
-				xcoffSect.Srelptr = uint64(ctxt.Out.Offset())
-				xcoffSect.Snreloc = relocsect(sect, dwarfp, sect.Vaddr)
-				continue dwarfLoop
-			}
-		}
-		Errorf(nil, "emitRelocations: could not find %q section", sect.Name)
-	}
-}
-
-// xcoffCreateExportFile creates a file with exported symbols for
-// -Wl,-bE option.
-// ld won't export symbols unless they are listed in an export file.
-func xcoffCreateExportFile(ctxt *Link) (fname string) {
-	fname = filepath.Join(*flagTmpdir, "export_file.exp")
-	var buf bytes.Buffer
-
-	for _, s := range ctxt.Syms.Allsym {
-		if !s.Attr.CgoExport() {
-			continue
-		}
-		if !strings.HasPrefix(s.String(), "_cgoexp_") {
-			continue
-		}
-
-		// Retrieve the name of the initial symbol
-		// exported by cgo.
-		// The corresponding Go symbol is:
-		// _cgoexp_hashcode_symname.
-		name := strings.SplitN(s.Extname(), "_", 4)[3]
-
-		buf.Write([]byte(name + "\n"))
-	}
-
-	err := ioutil.WriteFile(fname, buf.Bytes(), 0666)
-	if err != nil {
-		Errorf(nil, "WriteFile %s failed: %v", fname, err)
-	}
-
-	return fname
-
-}
diff --git a/src/cmd/oldlink/internal/loadelf/ldelf.go b/src/cmd/oldlink/internal/loadelf/ldelf.go
deleted file mode 100644
index db37db9..0000000
--- a/src/cmd/oldlink/internal/loadelf/ldelf.go
+++ /dev/null
@@ -1,1282 +0,0 @@
-// Copyright 2017 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 loadelf implements an ELF file reader.
-package loadelf
-
-import (
-	"bytes"
-	"cmd/internal/bio"
-	"cmd/internal/objabi"
-	"cmd/internal/sys"
-	"cmd/oldlink/internal/loader"
-	"cmd/oldlink/internal/sym"
-	"debug/elf"
-	"encoding/binary"
-	"fmt"
-	"io"
-	"log"
-	"sort"
-	"strings"
-)
-
-/*
-Derived from Plan 9 from User Space's src/libmach/elf.h, elf.c
-http://code.swtch.com/plan9port/src/tip/src/libmach/
-
-	Copyright © 2004 Russ Cox.
-	Portions Copyright © 2008-2010 Google Inc.
-	Portions Copyright © 2010 The Go Authors.
-
-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.
-*/
-const (
-	ElfClassNone = 0
-	ElfClass32   = 1
-	ElfClass64   = 2
-)
-
-const (
-	ElfDataNone = 0
-	ElfDataLsb  = 1
-	ElfDataMsb  = 2
-)
-
-const (
-	ElfTypeNone         = 0
-	ElfTypeRelocatable  = 1
-	ElfTypeExecutable   = 2
-	ElfTypeSharedObject = 3
-	ElfTypeCore         = 4
-)
-
-const (
-	ElfMachNone        = 0
-	ElfMach32100       = 1
-	ElfMachSparc       = 2
-	ElfMach386         = 3
-	ElfMach68000       = 4
-	ElfMach88000       = 5
-	ElfMach486         = 6
-	ElfMach860         = 7
-	ElfMachMips        = 8
-	ElfMachS370        = 9
-	ElfMachMipsLe      = 10
-	ElfMachParisc      = 15
-	ElfMachVpp500      = 17
-	ElfMachSparc32Plus = 18
-	ElfMach960         = 19
-	ElfMachPower       = 20
-	ElfMachPower64     = 21
-	ElfMachS390        = 22
-	ElfMachV800        = 36
-	ElfMachFr20        = 37
-	ElfMachRh32        = 38
-	ElfMachRce         = 39
-	ElfMachArm         = 40
-	ElfMachAlpha       = 41
-	ElfMachSH          = 42
-	ElfMachSparc9      = 43
-	ElfMachAmd64       = 62
-	ElfMachArm64       = 183
-)
-
-const (
-	ElfAbiNone     = 0
-	ElfAbiSystemV  = 0
-	ElfAbiHPUX     = 1
-	ElfAbiNetBSD   = 2
-	ElfAbiLinux    = 3
-	ElfAbiSolaris  = 6
-	ElfAbiAix      = 7
-	ElfAbiIrix     = 8
-	ElfAbiFreeBSD  = 9
-	ElfAbiTru64    = 10
-	ElfAbiModesto  = 11
-	ElfAbiOpenBSD  = 12
-	ElfAbiARM      = 97
-	ElfAbiEmbedded = 255
-)
-
-const (
-	ElfSectNone      = 0
-	ElfSectProgbits  = 1
-	ElfSectSymtab    = 2
-	ElfSectStrtab    = 3
-	ElfSectRela      = 4
-	ElfSectHash      = 5
-	ElfSectDynamic   = 6
-	ElfSectNote      = 7
-	ElfSectNobits    = 8
-	ElfSectRel       = 9
-	ElfSectShlib     = 10
-	ElfSectDynsym    = 11
-	ElfSectFlagWrite = 0x1
-	ElfSectFlagAlloc = 0x2
-	ElfSectFlagExec  = 0x4
-)
-
-const (
-	ElfSymBindLocal  = 0
-	ElfSymBindGlobal = 1
-	ElfSymBindWeak   = 2
-)
-
-const (
-	ElfSymTypeNone    = 0
-	ElfSymTypeObject  = 1
-	ElfSymTypeFunc    = 2
-	ElfSymTypeSection = 3
-	ElfSymTypeFile    = 4
-	ElfSymTypeCommon  = 5
-	ElfSymTypeTLS     = 6
-)
-
-const (
-	ElfSymShnNone   = 0
-	ElfSymShnAbs    = 0xFFF1
-	ElfSymShnCommon = 0xFFF2
-)
-
-const (
-	ElfProgNone      = 0
-	ElfProgLoad      = 1
-	ElfProgDynamic   = 2
-	ElfProgInterp    = 3
-	ElfProgNote      = 4
-	ElfProgShlib     = 5
-	ElfProgPhdr      = 6
-	ElfProgFlagExec  = 0x1
-	ElfProgFlagWrite = 0x2
-	ElfProgFlagRead  = 0x4
-)
-
-const (
-	ElfNotePrStatus     = 1
-	ElfNotePrFpreg      = 2
-	ElfNotePrPsinfo     = 3
-	ElfNotePrTaskstruct = 4
-	ElfNotePrAuxv       = 6
-	ElfNotePrXfpreg     = 0x46e62b7f
-)
-
-// TODO(crawshaw): de-duplicate with cmd/oldlink/internal/ld/elf.go.
-const (
-	ELF64SYMSIZE = 24
-	ELF32SYMSIZE = 16
-
-	SHT_ARM_ATTRIBUTES = 0x70000003
-)
-
-type ElfHdrBytes struct {
-	Ident     [16]uint8
-	Type      [2]uint8
-	Machine   [2]uint8
-	Version   [4]uint8
-	Entry     [4]uint8
-	Phoff     [4]uint8
-	Shoff     [4]uint8
-	Flags     [4]uint8
-	Ehsize    [2]uint8
-	Phentsize [2]uint8
-	Phnum     [2]uint8
-	Shentsize [2]uint8
-	Shnum     [2]uint8
-	Shstrndx  [2]uint8
-}
-
-type ElfSectBytes struct {
-	Name    [4]uint8
-	Type    [4]uint8
-	Flags   [4]uint8
-	Addr    [4]uint8
-	Off     [4]uint8
-	Size    [4]uint8
-	Link    [4]uint8
-	Info    [4]uint8
-	Align   [4]uint8
-	Entsize [4]uint8
-}
-
-type ElfProgBytes struct {
-}
-
-type ElfSymBytes struct {
-	Name  [4]uint8
-	Value [4]uint8
-	Size  [4]uint8
-	Info  uint8
-	Other uint8
-	Shndx [2]uint8
-}
-
-type ElfHdrBytes64 struct {
-	Ident     [16]uint8
-	Type      [2]uint8
-	Machine   [2]uint8
-	Version   [4]uint8
-	Entry     [8]uint8
-	Phoff     [8]uint8
-	Shoff     [8]uint8
-	Flags     [4]uint8
-	Ehsize    [2]uint8
-	Phentsize [2]uint8
-	Phnum     [2]uint8
-	Shentsize [2]uint8
-	Shnum     [2]uint8
-	Shstrndx  [2]uint8
-}
-
-type ElfSectBytes64 struct {
-	Name    [4]uint8
-	Type    [4]uint8
-	Flags   [8]uint8
-	Addr    [8]uint8
-	Off     [8]uint8
-	Size    [8]uint8
-	Link    [4]uint8
-	Info    [4]uint8
-	Align   [8]uint8
-	Entsize [8]uint8
-}
-
-type ElfProgBytes64 struct {
-}
-
-type ElfSymBytes64 struct {
-	Name  [4]uint8
-	Info  uint8
-	Other uint8
-	Shndx [2]uint8
-	Value [8]uint8
-	Size  [8]uint8
-}
-
-type ElfSect struct {
-	name    string
-	nameoff uint32
-	type_   uint32
-	flags   uint64
-	addr    uint64
-	off     uint64
-	size    uint64
-	link    uint32
-	info    uint32
-	align   uint64
-	entsize uint64
-	base    []byte
-	sym     *sym.Symbol
-}
-
-type ElfObj struct {
-	f         *bio.Reader
-	base      int64 // offset in f where ELF begins
-	length    int64 // length of ELF
-	is64      int
-	name      string
-	e         binary.ByteOrder
-	sect      []ElfSect
-	nsect     uint
-	nsymtab   int
-	symtab    *ElfSect
-	symstr    *ElfSect
-	type_     uint32
-	machine   uint32
-	version   uint32
-	entry     uint64
-	phoff     uint64
-	shoff     uint64
-	flags     uint32
-	ehsize    uint32
-	phentsize uint32
-	phnum     uint32
-	shentsize uint32
-	shnum     uint32
-	shstrndx  uint32
-}
-
-type ElfSym struct {
-	name  string
-	value uint64
-	size  uint64
-	bind  uint8
-	type_ uint8
-	other uint8
-	shndx uint16
-	sym   *sym.Symbol
-}
-
-var ElfMagic = [4]uint8{0x7F, 'E', 'L', 'F'}
-
-const (
-	TagFile               = 1
-	TagCPUName            = 4
-	TagCPURawName         = 5
-	TagCompatibility      = 32
-	TagNoDefaults         = 64
-	TagAlsoCompatibleWith = 65
-	TagABIVFPArgs         = 28
-)
-
-type elfAttribute struct {
-	tag  uint64
-	sval string
-	ival uint64
-}
-
-type elfAttributeList struct {
-	data []byte
-	err  error
-}
-
-func (a *elfAttributeList) string() string {
-	if a.err != nil {
-		return ""
-	}
-	nul := bytes.IndexByte(a.data, 0)
-	if nul < 0 {
-		a.err = io.EOF
-		return ""
-	}
-	s := string(a.data[:nul])
-	a.data = a.data[nul+1:]
-	return s
-}
-
-func (a *elfAttributeList) uleb128() uint64 {
-	if a.err != nil {
-		return 0
-	}
-	v, size := binary.Uvarint(a.data)
-	a.data = a.data[size:]
-	return v
-}
-
-// Read an elfAttribute from the list following the rules used on ARM systems.
-func (a *elfAttributeList) armAttr() elfAttribute {
-	attr := elfAttribute{tag: a.uleb128()}
-	switch {
-	case attr.tag == TagCompatibility:
-		attr.ival = a.uleb128()
-		attr.sval = a.string()
-
-	case attr.tag == 64: // Tag_nodefaults has no argument
-
-	case attr.tag == 65: // Tag_also_compatible_with
-		// Not really, but we don't actually care about this tag.
-		attr.sval = a.string()
-
-	// Tag with string argument
-	case attr.tag == TagCPUName || attr.tag == TagCPURawName || (attr.tag >= 32 && attr.tag&1 != 0):
-		attr.sval = a.string()
-
-	default: // Tag with integer argument
-		attr.ival = a.uleb128()
-	}
-	return attr
-}
-
-func (a *elfAttributeList) done() bool {
-	if a.err != nil || len(a.data) == 0 {
-		return true
-	}
-	return false
-}
-
-// Look for the attribute that indicates the object uses the hard-float ABI (a
-// file-level attribute with tag Tag_VFP_arch and value 1). Unfortunately the
-// format used means that we have to parse all of the file-level attributes to
-// find the one we are looking for. This format is slightly documented in "ELF
-// for the ARM Architecture" but mostly this is derived from reading the source
-// to gold and readelf.
-func parseArmAttributes(e binary.ByteOrder, data []byte) (found bool, ehdrFlags uint32, err error) {
-	found = false
-	if data[0] != 'A' {
-		return false, 0, fmt.Errorf(".ARM.attributes has unexpected format %c\n", data[0])
-	}
-	data = data[1:]
-	for len(data) != 0 {
-		sectionlength := e.Uint32(data)
-		sectiondata := data[4:sectionlength]
-		data = data[sectionlength:]
-
-		nulIndex := bytes.IndexByte(sectiondata, 0)
-		if nulIndex < 0 {
-			return false, 0, fmt.Errorf("corrupt .ARM.attributes (section name not NUL-terminated)\n")
-		}
-		name := string(sectiondata[:nulIndex])
-		sectiondata = sectiondata[nulIndex+1:]
-
-		if name != "aeabi" {
-			continue
-		}
-		for len(sectiondata) != 0 {
-			subsectiontag, sz := binary.Uvarint(sectiondata)
-			subsectionsize := e.Uint32(sectiondata[sz:])
-			subsectiondata := sectiondata[sz+4 : subsectionsize]
-			sectiondata = sectiondata[subsectionsize:]
-
-			if subsectiontag != TagFile {
-				continue
-			}
-			attrList := elfAttributeList{data: subsectiondata}
-			for !attrList.done() {
-				attr := attrList.armAttr()
-				if attr.tag == TagABIVFPArgs && attr.ival == 1 {
-					found = true
-					ehdrFlags = 0x5000402 // has entry point, Version5 EABI, hard-float ABI
-				}
-			}
-			if attrList.err != nil {
-				return false, 0, fmt.Errorf("could not parse .ARM.attributes\n")
-			}
-		}
-	}
-	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.
-// 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
-// emit by scanning the attributes in the ELF file being loaded. The
-// 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) {
-	errorf := func(str string, args ...interface{}) ([]*sym.Symbol, uint32, error) {
-		return nil, 0, fmt.Errorf("loadelf: %s: %v", pn, fmt.Sprintf(str, args...))
-	}
-
-	base := f.Offset()
-
-	var hdrbuf [64]uint8
-	if _, err := io.ReadFull(f, hdrbuf[:]); err != nil {
-		return errorf("malformed elf file: %v", err)
-	}
-	hdr := new(ElfHdrBytes)
-	binary.Read(bytes.NewReader(hdrbuf[:]), binary.BigEndian, hdr) // only byte arrays; byte order doesn't matter
-	if string(hdr.Ident[:4]) != "\x7FELF" {
-		return errorf("malformed elf file, bad header")
-	}
-	var e binary.ByteOrder
-	switch hdr.Ident[5] {
-	case ElfDataLsb:
-		e = binary.LittleEndian
-
-	case ElfDataMsb:
-		e = binary.BigEndian
-
-	default:
-		return errorf("malformed elf file, unknown header")
-	}
-
-	// read header
-	elfobj := new(ElfObj)
-
-	elfobj.e = e
-	elfobj.f = f
-	elfobj.base = base
-	elfobj.length = length
-	elfobj.name = pn
-
-	is64 := 0
-	if hdr.Ident[4] == ElfClass64 {
-		is64 = 1
-		hdr := new(ElfHdrBytes64)
-		binary.Read(bytes.NewReader(hdrbuf[:]), binary.BigEndian, hdr) // only byte arrays; byte order doesn't matter
-		elfobj.type_ = uint32(e.Uint16(hdr.Type[:]))
-		elfobj.machine = uint32(e.Uint16(hdr.Machine[:]))
-		elfobj.version = e.Uint32(hdr.Version[:])
-		elfobj.phoff = e.Uint64(hdr.Phoff[:])
-		elfobj.shoff = e.Uint64(hdr.Shoff[:])
-		elfobj.flags = e.Uint32(hdr.Flags[:])
-		elfobj.ehsize = uint32(e.Uint16(hdr.Ehsize[:]))
-		elfobj.phentsize = uint32(e.Uint16(hdr.Phentsize[:]))
-		elfobj.phnum = uint32(e.Uint16(hdr.Phnum[:]))
-		elfobj.shentsize = uint32(e.Uint16(hdr.Shentsize[:]))
-		elfobj.shnum = uint32(e.Uint16(hdr.Shnum[:]))
-		elfobj.shstrndx = uint32(e.Uint16(hdr.Shstrndx[:]))
-	} else {
-		elfobj.type_ = uint32(e.Uint16(hdr.Type[:]))
-		elfobj.machine = uint32(e.Uint16(hdr.Machine[:]))
-		elfobj.version = e.Uint32(hdr.Version[:])
-		elfobj.entry = uint64(e.Uint32(hdr.Entry[:]))
-		elfobj.phoff = uint64(e.Uint32(hdr.Phoff[:]))
-		elfobj.shoff = uint64(e.Uint32(hdr.Shoff[:]))
-		elfobj.flags = e.Uint32(hdr.Flags[:])
-		elfobj.ehsize = uint32(e.Uint16(hdr.Ehsize[:]))
-		elfobj.phentsize = uint32(e.Uint16(hdr.Phentsize[:]))
-		elfobj.phnum = uint32(e.Uint16(hdr.Phnum[:]))
-		elfobj.shentsize = uint32(e.Uint16(hdr.Shentsize[:]))
-		elfobj.shnum = uint32(e.Uint16(hdr.Shnum[:]))
-		elfobj.shstrndx = uint32(e.Uint16(hdr.Shstrndx[:]))
-	}
-
-	elfobj.is64 = is64
-
-	if v := uint32(hdr.Ident[6]); v != elfobj.version {
-		return errorf("malformed elf version: got %d, want %d", v, elfobj.version)
-	}
-
-	if e.Uint16(hdr.Type[:]) != ElfTypeRelocatable {
-		return errorf("elf but not elf relocatable object")
-	}
-
-	switch arch.Family {
-	default:
-		return errorf("elf %s unimplemented", arch.Name)
-
-	case sys.MIPS:
-		if elfobj.machine != ElfMachMips || hdr.Ident[4] != ElfClass32 {
-			return errorf("elf object but not mips")
-		}
-
-	case sys.MIPS64:
-		if elfobj.machine != ElfMachMips || hdr.Ident[4] != ElfClass64 {
-			return errorf("elf object but not mips64")
-		}
-
-	case sys.ARM:
-		if e != binary.LittleEndian || elfobj.machine != ElfMachArm || hdr.Ident[4] != ElfClass32 {
-			return errorf("elf object but not arm")
-		}
-
-	case sys.AMD64:
-		if e != binary.LittleEndian || elfobj.machine != ElfMachAmd64 || hdr.Ident[4] != ElfClass64 {
-			return errorf("elf object but not amd64")
-		}
-
-	case sys.ARM64:
-		if e != binary.LittleEndian || elfobj.machine != ElfMachArm64 || hdr.Ident[4] != ElfClass64 {
-			return errorf("elf object but not arm64")
-		}
-
-	case sys.I386:
-		if e != binary.LittleEndian || elfobj.machine != ElfMach386 || hdr.Ident[4] != ElfClass32 {
-			return errorf("elf object but not 386")
-		}
-
-	case sys.PPC64:
-		if elfobj.machine != ElfMachPower64 || hdr.Ident[4] != ElfClass64 {
-			return errorf("elf object but not ppc64")
-		}
-
-	case sys.S390X:
-		if elfobj.machine != ElfMachS390 || hdr.Ident[4] != ElfClass64 {
-			return errorf("elf object but not s390x")
-		}
-	}
-
-	// load section list into memory.
-	elfobj.sect = make([]ElfSect, elfobj.shnum)
-
-	elfobj.nsect = uint(elfobj.shnum)
-	for i := 0; uint(i) < elfobj.nsect; i++ {
-		f.MustSeek(int64(uint64(base)+elfobj.shoff+uint64(int64(i)*int64(elfobj.shentsize))), 0)
-		sect := &elfobj.sect[i]
-		if is64 != 0 {
-			var b ElfSectBytes64
-
-			if err := binary.Read(f, e, &b); err != nil {
-				return errorf("malformed elf file: %v", err)
-			}
-
-			sect.nameoff = e.Uint32(b.Name[:])
-			sect.type_ = e.Uint32(b.Type[:])
-			sect.flags = e.Uint64(b.Flags[:])
-			sect.addr = e.Uint64(b.Addr[:])
-			sect.off = e.Uint64(b.Off[:])
-			sect.size = e.Uint64(b.Size[:])
-			sect.link = e.Uint32(b.Link[:])
-			sect.info = e.Uint32(b.Info[:])
-			sect.align = e.Uint64(b.Align[:])
-			sect.entsize = e.Uint64(b.Entsize[:])
-		} else {
-			var b ElfSectBytes
-
-			if err := binary.Read(f, e, &b); err != nil {
-				return errorf("malformed elf file: %v", err)
-			}
-
-			sect.nameoff = e.Uint32(b.Name[:])
-			sect.type_ = e.Uint32(b.Type[:])
-			sect.flags = uint64(e.Uint32(b.Flags[:]))
-			sect.addr = uint64(e.Uint32(b.Addr[:]))
-			sect.off = uint64(e.Uint32(b.Off[:]))
-			sect.size = uint64(e.Uint32(b.Size[:]))
-			sect.link = e.Uint32(b.Link[:])
-			sect.info = e.Uint32(b.Info[:])
-			sect.align = uint64(e.Uint32(b.Align[:]))
-			sect.entsize = uint64(e.Uint32(b.Entsize[:]))
-		}
-	}
-
-	// read section string table and translate names
-	if elfobj.shstrndx >= uint32(elfobj.nsect) {
-		return errorf("malformed elf file: shstrndx out of range %d >= %d", elfobj.shstrndx, elfobj.nsect)
-	}
-
-	sect := &elfobj.sect[elfobj.shstrndx]
-	if err := elfmap(elfobj, sect); err != nil {
-		return errorf("malformed elf file: %v", err)
-	}
-	for i := 0; uint(i) < elfobj.nsect; i++ {
-		if elfobj.sect[i].nameoff != 0 {
-			elfobj.sect[i].name = cstring(sect.base[elfobj.sect[i].nameoff:])
-		}
-	}
-
-	// load string table for symbols into memory.
-	elfobj.symtab = section(elfobj, ".symtab")
-
-	if elfobj.symtab == nil {
-		// our work is done here - no symbols means nothing can refer to this file
-		return
-	}
-
-	if elfobj.symtab.link <= 0 || elfobj.symtab.link >= uint32(elfobj.nsect) {
-		return errorf("elf object has symbol table with invalid string table link")
-	}
-
-	elfobj.symstr = &elfobj.sect[elfobj.symtab.link]
-	if is64 != 0 {
-		elfobj.nsymtab = int(elfobj.symtab.size / ELF64SYMSIZE)
-	} else {
-		elfobj.nsymtab = int(elfobj.symtab.size / ELF32SYMSIZE)
-	}
-
-	if err := elfmap(elfobj, elfobj.symtab); err != nil {
-		return errorf("malformed elf file: %v", err)
-	}
-	if err := elfmap(elfobj, elfobj.symstr); err != nil {
-		return errorf("malformed elf file: %v", err)
-	}
-
-	// load text and data segments into memory.
-	// they are not as small as the section lists, but we'll need
-	// the memory anyway for the symbol images, so we might
-	// as well use one large chunk.
-
-	// create symbols for elfmapped sections
-	sectsymNames := make(map[string]bool)
-	counter := 0
-	for i := 0; uint(i) < elfobj.nsect; i++ {
-		sect = &elfobj.sect[i]
-		if sect.type_ == SHT_ARM_ATTRIBUTES && sect.name == ".ARM.attributes" {
-			if err := elfmap(elfobj, sect); err != nil {
-				return errorf("%s: malformed elf file: %v", pn, err)
-			}
-			// We assume the soft-float ABI unless we see a tag indicating otherwise.
-			if initEhdrFlags == 0x5000002 {
-				ehdrFlags = 0x5000202
-			} else {
-				ehdrFlags = initEhdrFlags
-			}
-			found, newEhdrFlags, err := parseArmAttributes(e, sect.base[:sect.size])
-			if err != nil {
-				// TODO(dfc) should this return an error?
-				log.Printf("%s: %v", pn, err)
-			}
-			if found {
-				ehdrFlags = newEhdrFlags
-			}
-		}
-		if (sect.type_ != ElfSectProgbits && sect.type_ != ElfSectNobits) || sect.flags&ElfSectFlagAlloc == 0 {
-			continue
-		}
-		if sect.type_ != ElfSectNobits {
-			if err := elfmap(elfobj, sect); err != nil {
-				return errorf("%s: malformed elf file: %v", pn, err)
-			}
-		}
-
-		name := fmt.Sprintf("%s(%s)", pkg, sect.name)
-		for sectsymNames[name] {
-			counter++
-			name = fmt.Sprintf("%s(%s%d)", pkg, sect.name, counter)
-		}
-		sectsymNames[name] = true
-
-		s := lookup(name, localSymVersion)
-
-		switch int(sect.flags) & (ElfSectFlagAlloc | ElfSectFlagWrite | ElfSectFlagExec) {
-		default:
-			return errorf("%s: unexpected flags for ELF section %s", pn, sect.name)
-
-		case ElfSectFlagAlloc:
-			s.Type = sym.SRODATA
-
-		case ElfSectFlagAlloc + ElfSectFlagWrite:
-			if sect.type_ == ElfSectNobits {
-				s.Type = sym.SNOPTRBSS
-			} else {
-				s.Type = sym.SNOPTRDATA
-			}
-
-		case ElfSectFlagAlloc + ElfSectFlagExec:
-			s.Type = sym.STEXT
-		}
-
-		if sect.name == ".got" || sect.name == ".toc" {
-			s.Type = sym.SELFGOT
-		}
-		if sect.type_ == ElfSectProgbits {
-			s.P = sect.base
-			s.P = s.P[:sect.size]
-		}
-
-		s.Size = int64(sect.size)
-		s.Align = int32(sect.align)
-		sect.sym = s
-	}
-
-	// enter sub-symbols into symbol table.
-	// symbol 0 is the null symbol.
-	symbols := make([]*sym.Symbol, elfobj.nsymtab)
-
-	for i := 1; i < elfobj.nsymtab; i++ {
-		var elfsym ElfSym
-		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
-		if elfsym.type_ != ElfSymTypeFunc && elfsym.type_ != ElfSymTypeObject && elfsym.type_ != ElfSymTypeNone && elfsym.type_ != ElfSymTypeCommon {
-			continue
-		}
-		if elfsym.shndx == ElfSymShnCommon || elfsym.type_ == ElfSymTypeCommon {
-			s := elfsym.sym
-			if uint64(s.Size) < elfsym.size {
-				s.Size = int64(elfsym.size)
-			}
-			if s.Type == 0 || s.Type == sym.SXREF {
-				s.Type = sym.SNOPTRBSS
-			}
-			continue
-		}
-
-		if uint(elfsym.shndx) >= elfobj.nsect || elfsym.shndx == 0 {
-			continue
-		}
-
-		// even when we pass needSym == 1 to readelfsym, it might still return nil to skip some unwanted symbols
-		if elfsym.sym == nil {
-			continue
-		}
-		sect = &elfobj.sect[elfsym.shndx]
-		if sect.sym == nil {
-			if strings.HasPrefix(elfsym.name, ".Linfo_string") { // clang does this
-				continue
-			}
-
-			if elfsym.name == "" && elfsym.type_ == 0 && sect.name == ".debug_str" {
-				// This reportedly happens with clang 3.7 on ARM.
-				// See issue 13139.
-				continue
-			}
-
-			if strings.HasPrefix(elfsym.name, "$d") && elfsym.type_ == 0 && sect.name == ".debug_frame" {
-				// "$d" is a marker, not a real symbol.
-				// This happens with gcc on ARM64.
-				// See https://sourceware.org/bugzilla/show_bug.cgi?id=21809
-				continue
-			}
-
-			if strings.HasPrefix(elfsym.name, ".LASF") { // gcc on s390x does this
-				continue
-			}
-			return errorf("%v: sym#%d: ignoring symbol in section %d (type %d)", elfsym.sym, i, elfsym.shndx, elfsym.type_)
-		}
-
-		s := elfsym.sym
-		if s.Outer != nil {
-			if s.Attr.DuplicateOK() {
-				continue
-			}
-			return errorf("duplicate symbol reference: %s in both %s and %s", s.Name, s.Outer.Name, sect.sym.Name)
-		}
-
-		s.Sub = sect.sym.Sub
-		sect.sym.Sub = s
-		s.Type = sect.sym.Type
-		s.Attr |= sym.AttrSubSymbol
-		if !s.Attr.CgoExportDynamic() {
-			s.SetDynimplib("") // satisfy dynimport
-		}
-		s.Value = int64(elfsym.value)
-		s.Size = int64(elfsym.size)
-		s.Outer = sect.sym
-		if sect.sym.Type == sym.STEXT {
-			if s.Attr.External() && !s.Attr.DuplicateOK() {
-				return errorf("%v: duplicate symbol definition", s)
-			}
-			s.Attr |= sym.AttrExternal
-		}
-
-		if elfobj.machine == ElfMachPower64 {
-			flag := int(elfsym.other) >> 5
-			if 2 <= flag && flag <= 6 {
-				s.SetLocalentry(1 << uint(flag-2))
-			} else if flag == 7 {
-				return errorf("%v: invalid sym.other 0x%x", s, elfsym.other)
-			}
-		}
-	}
-
-	// Sort outer lists by address, adding to textp.
-	// This keeps textp in increasing address order.
-	for i := uint(0); i < elfobj.nsect; i++ {
-		s := elfobj.sect[i].sym
-		if s == nil {
-			continue
-		}
-		if s.Sub != nil {
-			s.Sub = sym.SortSub(s.Sub)
-		}
-		if s.Type == sym.STEXT {
-			if s.Attr.OnList() {
-				return errorf("symbol %s listed multiple times", s.Name)
-			}
-			s.Attr |= sym.AttrOnList
-			textp = append(textp, s)
-			for s = s.Sub; s != nil; s = s.Sub {
-				if s.Attr.OnList() {
-					return errorf("symbol %s listed multiple times", s.Name)
-				}
-				s.Attr |= sym.AttrOnList
-				textp = append(textp, s)
-			}
-		}
-	}
-
-	// load relocations
-	for i := uint(0); i < elfobj.nsect; i++ {
-		rsect := &elfobj.sect[i]
-		if rsect.type_ != ElfSectRela && rsect.type_ != ElfSectRel {
-			continue
-		}
-		if rsect.info >= uint32(elfobj.nsect) || elfobj.sect[rsect.info].base == nil {
-			continue
-		}
-		sect = &elfobj.sect[rsect.info]
-		if err := elfmap(elfobj, rsect); err != nil {
-			return errorf("malformed elf file: %v", err)
-		}
-		rela := 0
-		if rsect.type_ == ElfSectRela {
-			rela = 1
-		}
-		n := int(rsect.size / uint64(4+4*is64) / uint64(2+rela))
-		r := make([]sym.Reloc, n)
-		p := rsect.base
-		for j := 0; j < n; j++ {
-			var add uint64
-			var symIdx int
-			var relocType uint64
-
-			rp := &r[j]
-			if is64 != 0 {
-				// 64-bit rel/rela
-				rp.Off = int32(e.Uint64(p))
-
-				p = p[8:]
-				switch arch.Family {
-				case sys.MIPS64:
-					// https://www.linux-mips.org/pub/linux/mips/doc/ABI/elf64-2.4.pdf
-					// The doc shows it's different with general Linux ELF
-					symIdx = int(e.Uint32(p))
-					relocType = uint64(p[7])
-				default:
-					info := e.Uint64(p)
-					relocType = info & 0xffffffff
-					symIdx = int(info >> 32)
-				}
-				p = p[8:]
-				if rela != 0 {
-					add = e.Uint64(p)
-					p = p[8:]
-				}
-			} else {
-				// 32-bit rel/rela
-				rp.Off = int32(e.Uint32(p))
-
-				p = p[4:]
-				info := e.Uint32(p)
-				relocType = uint64(info & 0xff)
-				symIdx = int(info >> 8)
-				p = p[4:]
-				if rela != 0 {
-					add = uint64(e.Uint32(p))
-					p = p[4:]
-				}
-			}
-
-			if relocType == 0 { // skip R_*_NONE relocation
-				j--
-				n--
-				continue
-			}
-
-			if symIdx == 0 { // absolute relocation, don't bother reading the null symbol
-				rp.Sym = nil
-			} else {
-				var elfsym ElfSym
-				if err := readelfsym(newSym, lookup, arch, elfobj, symIdx, &elfsym, 0, 0); err != nil {
-					return errorf("malformed elf file: %v", err)
-				}
-				elfsym.sym = symbols[symIdx]
-				if elfsym.sym == nil {
-					return errorf("malformed elf file: %s#%d: reloc of invalid sym #%d %s shndx=%d type=%d", sect.sym.Name, j, symIdx, elfsym.name, elfsym.shndx, elfsym.type_)
-				}
-
-				rp.Sym = elfsym.sym
-			}
-
-			rp.Type = objabi.ElfRelocOffset + objabi.RelocType(relocType)
-			rp.Siz, err = relSize(arch, pn, uint32(relocType))
-			if err != nil {
-				return nil, 0, err
-			}
-			if rela != 0 {
-				rp.Add = int64(add)
-			} else {
-				// load addend from image
-				if rp.Siz == 4 {
-					rp.Add = int64(e.Uint32(sect.base[rp.Off:]))
-				} else if rp.Siz == 8 {
-					rp.Add = int64(e.Uint64(sect.base[rp.Off:]))
-				} else {
-					return errorf("invalid rela size %d", rp.Siz)
-				}
-			}
-
-			if rp.Siz == 2 {
-				rp.Add = int64(int16(rp.Add))
-			}
-			if rp.Siz == 4 {
-				rp.Add = int64(int32(rp.Add))
-			}
-		}
-
-		//print("rel %s %d %d %s %#llx\n", sect->sym->name, rp->type, rp->siz, rp->sym->name, rp->add);
-		sort.Sort(sym.RelocByOff(r[:n]))
-		// just in case
-
-		s := sect.sym
-		s.R = r
-		s.R = s.R[:n]
-	}
-
-	return textp, ehdrFlags, nil
-}
-
-func section(elfobj *ElfObj, name string) *ElfSect {
-	for i := 0; uint(i) < elfobj.nsect; i++ {
-		if elfobj.sect[i].name != "" && name != "" && elfobj.sect[i].name == name {
-			return &elfobj.sect[i]
-		}
-	}
-	return nil
-}
-
-func elfmap(elfobj *ElfObj, sect *ElfSect) (err error) {
-	if sect.base != nil {
-		return nil
-	}
-
-	if sect.off+sect.size > uint64(elfobj.length) {
-		err = fmt.Errorf("elf section past end of file")
-		return err
-	}
-
-	sect.base = make([]byte, sect.size)
-	elfobj.f.MustSeek(int64(uint64(elfobj.base)+sect.off), 0)
-	if _, err := io.ReadFull(elfobj.f, sect.base); err != nil {
-		return fmt.Errorf("short read: %v", err)
-	}
-
-	return nil
-}
-
-func readelfsym(newSym, lookup lookupFunc, 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
-	}
-
-	if i == 0 {
-		return fmt.Errorf("readym: read null symbol!")
-	}
-
-	if elfobj.is64 != 0 {
-		b := new(ElfSymBytes64)
-		binary.Read(bytes.NewReader(elfobj.symtab.base[i*ELF64SYMSIZE:(i+1)*ELF64SYMSIZE]), elfobj.e, b)
-		elfsym.name = cstring(elfobj.symstr.base[elfobj.e.Uint32(b.Name[:]):])
-		elfsym.value = elfobj.e.Uint64(b.Value[:])
-		elfsym.size = elfobj.e.Uint64(b.Size[:])
-		elfsym.shndx = elfobj.e.Uint16(b.Shndx[:])
-		elfsym.bind = b.Info >> 4
-		elfsym.type_ = b.Info & 0xf
-		elfsym.other = b.Other
-	} else {
-		b := new(ElfSymBytes)
-		binary.Read(bytes.NewReader(elfobj.symtab.base[i*ELF32SYMSIZE:(i+1)*ELF32SYMSIZE]), elfobj.e, b)
-		elfsym.name = cstring(elfobj.symstr.base[elfobj.e.Uint32(b.Name[:]):])
-		elfsym.value = uint64(elfobj.e.Uint32(b.Value[:]))
-		elfsym.size = uint64(elfobj.e.Uint32(b.Size[:]))
-		elfsym.shndx = elfobj.e.Uint16(b.Shndx[:])
-		elfsym.bind = b.Info >> 4
-		elfsym.type_ = b.Info & 0xf
-		elfsym.other = b.Other
-	}
-
-	var s *sym.Symbol
-	if elfsym.name == "_GLOBAL_OFFSET_TABLE_" {
-		elfsym.name = ".got"
-	}
-	if elfsym.name == ".TOC." {
-		// Magic symbol on ppc64.  Will be set to this object
-		// file's .got+0x8000.
-		elfsym.bind = ElfSymBindLocal
-	}
-
-	switch elfsym.type_ {
-	case ElfSymTypeSection:
-		s = elfobj.sect[elfsym.shndx].sym
-
-	case ElfSymTypeObject, ElfSymTypeFunc, ElfSymTypeNone, ElfSymTypeCommon:
-		switch elfsym.bind {
-		case ElfSymBindGlobal:
-			if needSym != 0 {
-				s = lookup(elfsym.name, 0)
-
-				// for global scoped hidden symbols we should insert it into
-				// symbol hash table, but mark them as hidden.
-				// __i686.get_pc_thunk.bx is allowed to be duplicated, to
-				// workaround that we set dupok.
-				// TODO(minux): correctly handle __i686.get_pc_thunk.bx without
-				// set dupok generally. See https://golang.org/cl/5823055
-				// comment #5 for details.
-				if s != nil && elfsym.other == 2 {
-					s.Attr |= sym.AttrDuplicateOK | sym.AttrVisibilityHidden
-				}
-			}
-
-		case ElfSymBindLocal:
-			if (arch.Family == sys.ARM || arch.Family == sys.ARM64) && (strings.HasPrefix(elfsym.name, "$a") || strings.HasPrefix(elfsym.name, "$d") || strings.HasPrefix(elfsym.name, "$x")) {
-				// binutils for arm and arm64 generate these mapping
-				// symbols, ignore these
-				break
-			}
-
-			if elfsym.name == ".TOC." {
-				// We need to be able to look this up,
-				// so put it in the hash table.
-				if needSym != 0 {
-					s = lookup(elfsym.name, localSymVersion)
-					s.Attr |= sym.AttrVisibilityHidden
-				}
-
-				break
-			}
-
-			if needSym != 0 {
-				// 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
-				// 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
-			}
-
-		case ElfSymBindWeak:
-			if needSym != 0 {
-				s = lookup(elfsym.name, 0)
-				if elfsym.other == 2 {
-					s.Attr |= sym.AttrVisibilityHidden
-				}
-
-				// Allow weak symbols to be duplicated when already defined.
-				if s.Outer != nil {
-					s.Attr |= sym.AttrDuplicateOK
-				}
-			}
-
-		default:
-			err = fmt.Errorf("%s: invalid symbol binding %d", elfsym.name, elfsym.bind)
-			return err
-		}
-	}
-
-	// TODO(mwhudson): the test of VisibilityHidden here probably doesn't make
-	// sense and should be removed when someone has thought about it properly.
-	if s != nil && s.Type == 0 && !s.Attr.VisibilityHidden() && elfsym.type_ != ElfSymTypeSection {
-		s.Type = sym.SXREF
-	}
-	elfsym.sym = s
-
-	return nil
-}
-
-func relSize(arch *sys.Arch, pn string, elftype uint32) (uint8, error) {
-	// TODO(mdempsky): Replace this with a struct-valued switch statement
-	// once golang.org/issue/15164 is fixed or found to not impair cmd/link
-	// performance.
-
-	const (
-		AMD64  = uint32(sys.AMD64)
-		ARM    = uint32(sys.ARM)
-		ARM64  = uint32(sys.ARM64)
-		I386   = uint32(sys.I386)
-		PPC64  = uint32(sys.PPC64)
-		S390X  = uint32(sys.S390X)
-		MIPS   = uint32(sys.MIPS)
-		MIPS64 = uint32(sys.MIPS64)
-	)
-
-	switch uint32(arch.Family) | elftype<<16 {
-	default:
-		return 0, fmt.Errorf("%s: unknown relocation type %d; compiled without -fpic?", pn, elftype)
-
-	case MIPS | uint32(elf.R_MIPS_HI16)<<16,
-		MIPS | uint32(elf.R_MIPS_LO16)<<16,
-		MIPS | uint32(elf.R_MIPS_GOT16)<<16,
-		MIPS | uint32(elf.R_MIPS_GPREL16)<<16,
-		MIPS | uint32(elf.R_MIPS_GOT_PAGE)<<16,
-		MIPS | uint32(elf.R_MIPS_JALR)<<16,
-		MIPS | uint32(elf.R_MIPS_GOT_OFST)<<16,
-		MIPS64 | uint32(elf.R_MIPS_HI16)<<16,
-		MIPS64 | uint32(elf.R_MIPS_LO16)<<16,
-		MIPS64 | uint32(elf.R_MIPS_GOT16)<<16,
-		MIPS64 | uint32(elf.R_MIPS_GPREL16)<<16,
-		MIPS64 | uint32(elf.R_MIPS_GOT_PAGE)<<16,
-		MIPS64 | uint32(elf.R_MIPS_JALR)<<16,
-		MIPS64 | uint32(elf.R_MIPS_GOT_OFST)<<16:
-		return 4, nil
-
-	case S390X | uint32(elf.R_390_8)<<16:
-		return 1, nil
-
-	case PPC64 | uint32(elf.R_PPC64_TOC16)<<16,
-		PPC64 | uint32(elf.R_PPC64_TOC16_LO)<<16,
-		PPC64 | uint32(elf.R_PPC64_TOC16_HI)<<16,
-		PPC64 | uint32(elf.R_PPC64_TOC16_HA)<<16,
-		PPC64 | uint32(elf.R_PPC64_TOC16_DS)<<16,
-		PPC64 | uint32(elf.R_PPC64_TOC16_LO_DS)<<16,
-		PPC64 | uint32(elf.R_PPC64_REL16_LO)<<16,
-		PPC64 | uint32(elf.R_PPC64_REL16_HI)<<16,
-		PPC64 | uint32(elf.R_PPC64_REL16_HA)<<16,
-		S390X | uint32(elf.R_390_16)<<16,
-		S390X | uint32(elf.R_390_GOT16)<<16,
-		S390X | uint32(elf.R_390_PC16)<<16,
-		S390X | uint32(elf.R_390_PC16DBL)<<16,
-		S390X | uint32(elf.R_390_PLT16DBL)<<16:
-		return 2, nil
-
-	case ARM | uint32(elf.R_ARM_ABS32)<<16,
-		ARM | uint32(elf.R_ARM_GOT32)<<16,
-		ARM | uint32(elf.R_ARM_PLT32)<<16,
-		ARM | uint32(elf.R_ARM_GOTOFF)<<16,
-		ARM | uint32(elf.R_ARM_GOTPC)<<16,
-		ARM | uint32(elf.R_ARM_THM_PC22)<<16,
-		ARM | uint32(elf.R_ARM_REL32)<<16,
-		ARM | uint32(elf.R_ARM_CALL)<<16,
-		ARM | uint32(elf.R_ARM_V4BX)<<16,
-		ARM | uint32(elf.R_ARM_GOT_PREL)<<16,
-		ARM | uint32(elf.R_ARM_PC24)<<16,
-		ARM | uint32(elf.R_ARM_JUMP24)<<16,
-		ARM64 | uint32(elf.R_AARCH64_CALL26)<<16,
-		ARM64 | uint32(elf.R_AARCH64_ADR_GOT_PAGE)<<16,
-		ARM64 | uint32(elf.R_AARCH64_LD64_GOT_LO12_NC)<<16,
-		ARM64 | uint32(elf.R_AARCH64_ADR_PREL_PG_HI21)<<16,
-		ARM64 | uint32(elf.R_AARCH64_ADD_ABS_LO12_NC)<<16,
-		ARM64 | uint32(elf.R_AARCH64_LDST8_ABS_LO12_NC)<<16,
-		ARM64 | uint32(elf.R_AARCH64_LDST32_ABS_LO12_NC)<<16,
-		ARM64 | uint32(elf.R_AARCH64_LDST64_ABS_LO12_NC)<<16,
-		ARM64 | uint32(elf.R_AARCH64_LDST128_ABS_LO12_NC)<<16,
-		ARM64 | uint32(elf.R_AARCH64_PREL32)<<16,
-		ARM64 | uint32(elf.R_AARCH64_JUMP26)<<16,
-		AMD64 | uint32(elf.R_X86_64_PC32)<<16,
-		AMD64 | uint32(elf.R_X86_64_PLT32)<<16,
-		AMD64 | uint32(elf.R_X86_64_GOTPCREL)<<16,
-		AMD64 | uint32(elf.R_X86_64_GOTPCRELX)<<16,
-		AMD64 | uint32(elf.R_X86_64_REX_GOTPCRELX)<<16,
-		I386 | uint32(elf.R_386_32)<<16,
-		I386 | uint32(elf.R_386_PC32)<<16,
-		I386 | uint32(elf.R_386_GOT32)<<16,
-		I386 | uint32(elf.R_386_PLT32)<<16,
-		I386 | uint32(elf.R_386_GOTOFF)<<16,
-		I386 | uint32(elf.R_386_GOTPC)<<16,
-		I386 | uint32(elf.R_386_GOT32X)<<16,
-		PPC64 | uint32(elf.R_PPC64_REL24)<<16,
-		PPC64 | uint32(elf.R_PPC_REL32)<<16,
-		S390X | uint32(elf.R_390_32)<<16,
-		S390X | uint32(elf.R_390_PC32)<<16,
-		S390X | uint32(elf.R_390_GOT32)<<16,
-		S390X | uint32(elf.R_390_PLT32)<<16,
-		S390X | uint32(elf.R_390_PC32DBL)<<16,
-		S390X | uint32(elf.R_390_PLT32DBL)<<16,
-		S390X | uint32(elf.R_390_GOTPCDBL)<<16,
-		S390X | uint32(elf.R_390_GOTENT)<<16:
-		return 4, nil
-
-	case AMD64 | uint32(elf.R_X86_64_64)<<16,
-		AMD64 | uint32(elf.R_X86_64_PC64)<<16,
-		ARM64 | uint32(elf.R_AARCH64_ABS64)<<16,
-		ARM64 | uint32(elf.R_AARCH64_PREL64)<<16,
-		PPC64 | uint32(elf.R_PPC64_ADDR64)<<16,
-		S390X | uint32(elf.R_390_GLOB_DAT)<<16,
-		S390X | uint32(elf.R_390_RELATIVE)<<16,
-		S390X | uint32(elf.R_390_GOTOFF)<<16,
-		S390X | uint32(elf.R_390_GOTPC)<<16,
-		S390X | uint32(elf.R_390_64)<<16,
-		S390X | uint32(elf.R_390_PC64)<<16,
-		S390X | uint32(elf.R_390_GOT64)<<16,
-		S390X | uint32(elf.R_390_PLT64)<<16:
-		return 8, nil
-	}
-}
-
-func cstring(x []byte) string {
-	i := bytes.IndexByte(x, '\x00')
-	if i >= 0 {
-		x = x[:i]
-	}
-	return string(x)
-}
diff --git a/src/cmd/oldlink/internal/loader/loader.go b/src/cmd/oldlink/internal/loader/loader.go
deleted file mode 100644
index 8c618bf..0000000
--- a/src/cmd/oldlink/internal/loader/loader.go
+++ /dev/null
@@ -1,629 +0,0 @@
-// Copyright 2019 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 loader
-
-import (
-	"bytes"
-	"cmd/internal/bio"
-	"cmd/internal/dwarf"
-	"cmd/internal/objabi"
-	"cmd/internal/sys"
-	"cmd/oldlink/internal/sym"
-	"fmt"
-	"log"
-	"sort"
-	"strconv"
-	"strings"
-)
-
-var _ = fmt.Print
-
-// Sym encapsulates a global symbol index, used to identify a specific
-// Go symbol. The 0-valued Sym is corresponds to an invalid symbol.
-type Sym int
-
-// Relocs encapsulates the set of relocations on a given symbol; an
-// instance of this type is returned by the Loader Relocs() method.
-type Relocs struct {
-	Count int // number of relocs
-
-	li int      // local index of symbol whose relocs we're examining
-	r  *oReader // object reader for containing package
-	l  *Loader  // loader
-
-	ext *sym.Symbol // external symbol if not nil
-}
-
-// Reloc contains the payload for a specific relocation.
-// TODO: replace this with sym.Reloc, once we change the
-// relocation target from "*sym.Symbol" to "loader.Sym" in sym.Reloc.
-type Reloc struct {
-	Off  int32            // offset to rewrite
-	Size uint8            // number of bytes to rewrite: 0, 1, 2, or 4
-	Type objabi.RelocType // the relocation type
-	Add  int64            // addend
-	Sym  Sym              // global index of symbol the reloc addresses
-}
-
-// oReader is a wrapper type of obj.Reader, along with some
-// extra information.
-// TODO: rename to objReader once the old one is gone?
-type oReader struct {
-	//*goobj2.Reader
-	unit      *sym.CompilationUnit
-	version   int    // version of static symbol
-	flags     uint32 // read from object file
-	pkgprefix string
-	rcache    []Sym // cache mapping local PkgNone symbol to resolved Sym
-}
-
-type objIdx struct {
-	r *oReader
-	i Sym // start index
-	e Sym // end index
-}
-
-type nameVer struct {
-	name string
-	v    int
-}
-
-type bitmap []uint32
-
-// set the i-th bit.
-func (bm bitmap) Set(i Sym) {
-	n, r := uint(i)/32, uint(i)%32
-	bm[n] |= 1 << r
-}
-
-// whether the i-th bit is set.
-func (bm bitmap) Has(i Sym) bool {
-	n, r := uint(i)/32, uint(i)%32
-	return bm[n]&(1<<r) != 0
-}
-
-func makeBitmap(n int) bitmap {
-	return make(bitmap, (n+31)/32)
-}
-
-// A Loader loads new object files and resolves indexed symbol references.
-type Loader struct {
-	start       map[*oReader]Sym // map from object file to its start index
-	objs        []objIdx         // sorted by start index (i.e. objIdx.i)
-	max         Sym              // current max index
-	extStart    Sym              // from this index on, the symbols are externally defined
-	extSyms     []nameVer        // externally defined symbols
-	builtinSyms []Sym            // global index of builtin symbols
-	ocache      int              // index (into 'objs') of most recent lookup
-
-	symsByName    [2]map[string]Sym // map symbol name to index, two maps are for ABI0 and ABIInternal
-	extStaticSyms map[nameVer]Sym   // externally defined static symbols, keyed by name
-	overwrite     map[Sym]Sym       // overwrite[i]=j if symbol j overwrites symbol i
-
-	itablink map[Sym]struct{} // itablink[j] defined if j is go.itablink.*
-
-	objByPkg map[string]*oReader // map package path to its Go object reader
-
-	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
-	// field tracking is enabled. Reachparent[K] contains the index of
-	// the symbol that triggered the marking of symbol K as live.
-	Reachparent []Sym
-
-	relocBatch []sym.Reloc // for bulk allocation of relocations
-
-	flags uint32
-
-	strictDupMsgs int // number of strict-dup warning/errors, when FlagStrictDups is enabled
-}
-
-const (
-	// Loader.flags
-	FlagStrictDups = 1 << iota
-)
-
-func NewLoader(flags uint32) *Loader {
-	log.Fatal("-newobj in oldlink should not be used")
-	panic("unreachable")
-}
-
-// Return the start index in the global index space for a given object file.
-func (l *Loader) startIndex(r *oReader) Sym {
-	return l.start[r]
-}
-
-// Add a symbol with a given index, return if it is added.
-func (l *Loader) AddSym(name string, ver int, i Sym, r *oReader, dupok bool, typ sym.SymKind) bool {
-	panic("unreachable")
-}
-
-// Add an external symbol (without index). Return the index of newly added
-// symbol, or 0 if not added.
-func (l *Loader) AddExtSym(name string, ver int) Sym {
-	static := ver >= sym.SymVerStatic
-	if static {
-		if _, ok := l.extStaticSyms[nameVer{name, ver}]; ok {
-			return 0
-		}
-	} else {
-		if _, ok := l.symsByName[ver][name]; ok {
-			return 0
-		}
-	}
-	i := l.max + 1
-	if static {
-		l.extStaticSyms[nameVer{name, ver}] = i
-	} else {
-		l.symsByName[ver][name] = i
-	}
-	l.max++
-	if l.extStart == 0 {
-		l.extStart = i
-	}
-	l.extSyms = append(l.extSyms, nameVer{name, ver})
-	l.growSyms(int(i))
-	return i
-}
-
-func (l *Loader) IsExternal(i Sym) bool {
-	return l.extStart != 0 && i >= l.extStart
-}
-
-// Ensure Syms slice has enough space.
-func (l *Loader) growSyms(i int) {
-	n := len(l.Syms)
-	if n > i {
-		return
-	}
-	l.Syms = append(l.Syms, make([]*sym.Symbol, i+1-n)...)
-}
-
-// Convert a local index to a global index.
-func (l *Loader) toGlobal(r *oReader, i int) Sym {
-	g := l.startIndex(r) + Sym(i)
-	if ov, ok := l.overwrite[g]; ok {
-		return ov
-	}
-	return g
-}
-
-// Convert a global index to a local index.
-func (l *Loader) toLocal(i Sym) (*oReader, int) {
-	if ov, ok := l.overwrite[i]; ok {
-		i = ov
-	}
-	if l.IsExternal(i) {
-		return nil, int(i - l.extStart)
-	}
-	oc := l.ocache
-	if oc != 0 && i >= l.objs[oc].i && i <= l.objs[oc].e {
-		return l.objs[oc].r, int(i - l.objs[oc].i)
-	}
-	// Search for the local object holding index i.
-	// Below k is the first one that has its start index > i,
-	// so k-1 is the one we want.
-	k := sort.Search(len(l.objs), func(k int) bool {
-		return l.objs[k].i > i
-	})
-	l.ocache = k - 1
-	return l.objs[k-1].r, int(i - l.objs[k-1].i)
-}
-
-// Look up a symbol by name, return global index, or 0 if not found.
-// 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 || ver < 0 {
-		return l.extStaticSyms[nameVer{name, ver}]
-	}
-	return l.symsByName[ver][name]
-}
-
-// Returns whether i is a dup of another symbol, and i is not
-// "primary", i.e. Lookup i by name will not return i.
-func (l *Loader) IsDup(i Sym) bool {
-	panic("unreachable")
-}
-
-// Check that duplicate symbols have same contents.
-func (l *Loader) checkdup(name string, i Sym, r *oReader, dup Sym) {
-	panic("unreachable")
-}
-
-func (l *Loader) NStrictDupMsgs() int { return l.strictDupMsgs }
-
-// Number of total symbols.
-func (l *Loader) NSym() int {
-	return int(l.max + 1)
-}
-
-// Number of defined Go symbols.
-func (l *Loader) NDef() int {
-	return int(l.extStart)
-}
-
-// Returns the raw (unpatched) name of the i-th symbol.
-func (l *Loader) RawSymName(i Sym) string {
-	panic("unreachable")
-}
-
-// Returns the (patched) name of the i-th symbol.
-func (l *Loader) SymName(i Sym) string {
-	panic("unreachable")
-}
-
-// Returns the type of the i-th symbol.
-func (l *Loader) SymType(i Sym) sym.SymKind {
-	panic("unreachable")
-}
-
-// Returns the attributes of the i-th symbol.
-func (l *Loader) SymAttr(i Sym) uint8 {
-	panic("unreachable")
-}
-
-// Returns whether the i-th symbol has ReflectMethod attribute set.
-func (l *Loader) IsReflectMethod(i Sym) bool {
-	panic("unreachable")
-}
-
-// Returns whether this is a Go type symbol.
-func (l *Loader) IsGoType(i Sym) bool {
-	panic("unreachable")
-}
-
-// Returns whether this is a "go.itablink.*" symbol.
-func (l *Loader) IsItabLink(i Sym) bool {
-	if _, ok := l.itablink[i]; ok {
-		return true
-	}
-	return false
-}
-
-// Returns the symbol content of the i-th symbol. i is global index.
-func (l *Loader) Data(i Sym) []byte {
-	panic("unreachable")
-}
-
-// Returns the number of aux symbols given a global index.
-func (l *Loader) NAux(i Sym) int {
-	panic("unreachable")
-}
-
-// Returns the referred symbol of the j-th aux symbol of the i-th
-// symbol.
-func (l *Loader) AuxSym(i Sym, j int) Sym {
-	panic("unreachable")
-}
-
-// ReadAuxSyms reads the aux symbol ids for the specified symbol into the
-// slice passed as a parameter. If the slice capacity is not large enough, a new
-// larger slice will be allocated. Final slice is returned.
-func (l *Loader) ReadAuxSyms(symIdx Sym, dst []Sym) []Sym {
-	panic("unreachable")
-}
-
-// OuterSym gets the outer symbol for host object loaded symbols.
-func (l *Loader) OuterSym(i Sym) Sym {
-	sym := l.Syms[i]
-	if sym != nil && sym.Outer != nil {
-		outer := sym.Outer
-		return l.Lookup(outer.Name, int(outer.Version))
-	}
-	return 0
-}
-
-// SubSym gets the subsymbol for host object loaded symbols.
-func (l *Loader) SubSym(i Sym) Sym {
-	sym := l.Syms[i]
-	if sym != nil && sym.Sub != nil {
-		sub := sym.Sub
-		return l.Lookup(sub.Name, int(sub.Version))
-	}
-	return 0
-}
-
-// Initialize Reachable bitmap for running deadcode pass.
-func (l *Loader) InitReachable() {
-	l.Reachable = makeBitmap(l.NSym())
-}
-
-// At method returns the j-th reloc for a global symbol.
-func (relocs *Relocs) At(j int) Reloc {
-	panic("unreachable")
-}
-
-// ReadAll method reads all relocations for a symbol into the
-// specified slice. If the slice capacity is not large enough, a new
-// larger slice will be allocated. Final slice is returned.
-func (relocs *Relocs) ReadAll(dst []Reloc) []Reloc {
-	panic("unreachable")
-}
-
-// Relocs returns a Relocs object for the given global sym.
-func (l *Loader) Relocs(i Sym) Relocs {
-	panic("unreachable")
-}
-
-// Preload a package: add autolibs, add symbols to the symbol table.
-// Does not read symbol data yet.
-func (l *Loader) Preload(arch *sys.Arch, syms *sym.Symbols, f *bio.Reader, lib *sym.Library, unit *sym.CompilationUnit, length int64, pn string, flags int) {
-	panic("unreachable")
-}
-
-// Make sure referenced symbols are added. Most of them should already be added.
-// This should only be needed for referenced external symbols.
-func (l *Loader) LoadRefs(arch *sys.Arch, syms *sym.Symbols) {
-	for _, o := range l.objs[1:] {
-		loadObjRefs(l, o.r, arch, syms)
-	}
-}
-
-func loadObjRefs(l *Loader, r *oReader, arch *sys.Arch, syms *sym.Symbols) {
-	panic("unreachable")
-}
-
-func abiToVer(abi uint16, localSymVersion int) int {
-	panic("unreachable")
-}
-
-func preprocess(arch *sys.Arch, s *sym.Symbol) {
-	if s.Name != "" && s.Name[0] == '$' && len(s.Name) > 5 && s.Type == 0 && len(s.P) == 0 {
-		x, err := strconv.ParseUint(s.Name[5:], 16, 64)
-		if err != nil {
-			log.Panicf("failed to parse $-symbol %s: %v", s.Name, err)
-		}
-		s.Type = sym.SRODATA
-		s.Attr |= sym.AttrLocal
-		switch s.Name[:5] {
-		case "$f32.":
-			if uint64(uint32(x)) != x {
-				log.Panicf("$-symbol %s too large: %d", s.Name, x)
-			}
-			s.AddUint32(arch, uint32(x))
-		case "$f64.", "$i64.":
-			s.AddUint64(arch, x)
-		default:
-			log.Panicf("unrecognized $-symbol: %s", s.Name)
-		}
-	}
-}
-
-// Load full contents.
-func (l *Loader) LoadFull(arch *sys.Arch, syms *sym.Symbols) {
-	// create all Symbols first.
-	l.growSyms(l.NSym())
-
-	nr := 0 // total number of sym.Reloc's we'll need
-	for _, o := range l.objs[1:] {
-		nr += loadObjSyms(l, syms, o.r)
-	}
-
-	// allocate a single large slab of relocations for all live symbols
-	l.relocBatch = make([]sym.Reloc, nr)
-
-	// external symbols
-	for i := l.extStart; i <= l.max; i++ {
-		if s := l.Syms[i]; s != nil {
-			s.Attr.Set(sym.AttrReachable, l.Reachable.Has(i))
-			continue // already loaded from external object
-		}
-		nv := l.extSyms[i-l.extStart]
-		if l.Reachable.Has(i) || strings.HasPrefix(nv.name, "gofile..") { // XXX file symbols are used but not marked
-			s := syms.Newsym(nv.name, nv.v)
-			preprocess(arch, s)
-			s.Attr.Set(sym.AttrReachable, l.Reachable.Has(i))
-			l.Syms[i] = s
-		}
-	}
-
-	// load contents of defined symbols
-	for _, o := range l.objs[1:] {
-		loadObjFull(l, o.r)
-	}
-
-	// Resolve ABI aliases for external symbols. This is only
-	// needed for internal cgo linking.
-	// (The old code does this in deadcode, but deadcode2 doesn't
-	// do this.)
-	for i := l.extStart; i <= l.max; i++ {
-		if s := l.Syms[i]; s != nil && s.Attr.Reachable() {
-			for ri := range s.R {
-				r := &s.R[ri]
-				if r.Sym != nil && r.Sym.Type == sym.SABIALIAS {
-					r.Sym = r.Sym.R[0].Sym
-				}
-			}
-		}
-	}
-}
-
-// ExtractSymbols grabs the symbols out of the loader for work that hasn't been
-// ported to the new symbol type.
-func (l *Loader) ExtractSymbols(syms *sym.Symbols) {
-	// Nil out overwritten symbols.
-	// Overwritten Go symbols aren't a problem (as they're lazy loaded), but
-	// symbols loaded from host object loaders are fully loaded, and we might
-	// have multiple symbols with the same name. This loop nils them out.
-	for oldI := range l.overwrite {
-		l.Syms[oldI] = nil
-	}
-
-	// 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 {
-			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.
-func (l *Loader) addNewSym(i Sym, syms *sym.Symbols, name string, ver int, unit *sym.CompilationUnit, t sym.SymKind) *sym.Symbol {
-	s := syms.Newsym(name, ver)
-	if s.Type != 0 && s.Type != sym.SXREF {
-		fmt.Println("symbol already processed:", unit.Lib, i, s)
-		panic("symbol already processed")
-	}
-	if t == sym.SBSS && (s.Type == sym.SRODATA || s.Type == sym.SNOPTRBSS) {
-		t = s.Type
-	}
-	s.Type = t
-	s.Unit = unit
-	l.growSyms(int(i))
-	l.Syms[i] = s
-	return s
-}
-
-// loadObjSyms creates sym.Symbol objects for the live Syms in the
-// object corresponding to object reader "r". Return value is the
-// number of sym.Reloc entries required for all the new symbols.
-func loadObjSyms(l *Loader, syms *sym.Symbols, r *oReader) int {
-	panic("unreachable")
-}
-
-// LoadSymbol loads a single symbol by name.
-// This function should only be used by the host object loaders.
-// NB: This function does NOT set the symbol as reachable.
-func (l *Loader) LoadSymbol(name string, version int, syms *sym.Symbols) *sym.Symbol {
-	panic("unreachable")
-}
-
-// LookupOrCreate looks up a symbol by name, and creates one if not found.
-// Either way, it will also create a sym.Symbol for it, if not already.
-// This should only be called when interacting with parts of the linker
-// that still works on sym.Symbols (i.e. internal cgo linking, for now).
-func (l *Loader) LookupOrCreate(name string, version int, syms *sym.Symbols) *sym.Symbol {
-	i := l.Lookup(name, version)
-	if i != 0 {
-		// symbol exists
-		if int(i) < len(l.Syms) && l.Syms[i] != nil {
-			return l.Syms[i] // already loaded
-		}
-		if l.IsExternal(i) {
-			panic("Can't load an external symbol.")
-		}
-		return l.LoadSymbol(name, version, syms)
-	}
-	i = l.AddExtSym(name, version)
-	s := syms.Newsym(name, version)
-	l.Syms[i] = s
-	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) {
-	panic("unreachable")
-}
-
-var emptyPkg = []byte(`"".`)
-
-func patchDWARFName1(p []byte, r *oReader) ([]byte, int) {
-	// This is kind of ugly. Really the package name should not
-	// even be included here.
-	if len(p) < 1 || p[0] != dwarf.DW_ABRV_FUNCTION {
-		return p, -1
-	}
-	e := bytes.IndexByte(p, 0)
-	if e == -1 {
-		return p, -1
-	}
-	if !bytes.Contains(p[:e], emptyPkg) {
-		return p, -1
-	}
-	pkgprefix := []byte(r.pkgprefix)
-	patched := bytes.Replace(p[:e], emptyPkg, pkgprefix, -1)
-	return append(patched, p[e:]...), e
-}
-
-func patchDWARFName(s *sym.Symbol, r *oReader) {
-	patched, e := patchDWARFName1(s.P, r)
-	if e == -1 {
-		return
-	}
-	s.P = patched
-	s.Attr.Set(sym.AttrReadOnly, false)
-	delta := int64(len(s.P)) - s.Size
-	s.Size = int64(len(s.P))
-	for i := range s.R {
-		r := &s.R[i]
-		if r.Off > int32(e) {
-			r.Off += int32(delta)
-		}
-	}
-}
-
-// For debugging.
-func (l *Loader) Dump() {
-	fmt.Println("objs")
-	for _, obj := range l.objs {
-		if obj.r != nil {
-			fmt.Println(obj.i, obj.r.unit.Lib)
-		}
-	}
-	fmt.Println("syms")
-	for i, s := range l.Syms {
-		if i == 0 {
-			continue
-		}
-		if s != nil {
-			fmt.Println(i, s, s.Type)
-		} else {
-			fmt.Println(i, l.SymName(Sym(i)), "<not loaded>")
-		}
-	}
-	fmt.Println("overwrite:", l.overwrite)
-	fmt.Println("symsByName")
-	for name, i := range l.symsByName[0] {
-		fmt.Println(i, name, 0)
-	}
-	for name, i := range l.symsByName[1] {
-		fmt.Println(i, name, 1)
-	}
-}
diff --git a/src/cmd/oldlink/internal/loadmacho/ldmacho.go b/src/cmd/oldlink/internal/loadmacho/ldmacho.go
deleted file mode 100644
index 4846239..0000000
--- a/src/cmd/oldlink/internal/loadmacho/ldmacho.go
+++ /dev/null
@@ -1,794 +0,0 @@
-// Copyright 2017 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 loadmacho implements a Mach-O file reader.
-package loadmacho
-
-import (
-	"bytes"
-	"cmd/internal/bio"
-	"cmd/internal/objabi"
-	"cmd/internal/sys"
-	"cmd/oldlink/internal/loader"
-	"cmd/oldlink/internal/sym"
-	"encoding/binary"
-	"fmt"
-	"io"
-	"sort"
-)
-
-/*
-Derived from Plan 9 from User Space's src/libmach/elf.h, elf.c
-http://code.swtch.com/plan9port/src/tip/src/libmach/
-
-	Copyright © 2004 Russ Cox.
-	Portions Copyright © 2008-2010 Google Inc.
-	Portions Copyright © 2010 The Go Authors.
-
-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.
-*/
-
-// TODO(crawshaw): de-duplicate these symbols with cmd/internal/ld
-const (
-	MACHO_X86_64_RELOC_UNSIGNED = 0
-	MACHO_X86_64_RELOC_SIGNED   = 1
-	MACHO_FAKE_GOTPCREL         = 100
-)
-
-type ldMachoObj struct {
-	f          *bio.Reader
-	base       int64 // off in f where Mach-O begins
-	length     int64 // length of Mach-O
-	is64       bool
-	name       string
-	e          binary.ByteOrder
-	cputype    uint
-	subcputype uint
-	filetype   uint32
-	flags      uint32
-	cmd        []ldMachoCmd
-	ncmd       uint
-}
-
-type ldMachoCmd struct {
-	type_ int
-	off   uint32
-	size  uint32
-	seg   ldMachoSeg
-	sym   ldMachoSymtab
-	dsym  ldMachoDysymtab
-}
-
-type ldMachoSeg struct {
-	name     string
-	vmaddr   uint64
-	vmsize   uint64
-	fileoff  uint32
-	filesz   uint32
-	maxprot  uint32
-	initprot uint32
-	nsect    uint32
-	flags    uint32
-	sect     []ldMachoSect
-}
-
-type ldMachoSect struct {
-	name    string
-	segname string
-	addr    uint64
-	size    uint64
-	off     uint32
-	align   uint32
-	reloff  uint32
-	nreloc  uint32
-	flags   uint32
-	res1    uint32
-	res2    uint32
-	sym     *sym.Symbol
-	rel     []ldMachoRel
-}
-
-type ldMachoRel struct {
-	addr      uint32
-	symnum    uint32
-	pcrel     uint8
-	length    uint8
-	extrn     uint8
-	type_     uint8
-	scattered uint8
-	value     uint32
-}
-
-type ldMachoSymtab struct {
-	symoff  uint32
-	nsym    uint32
-	stroff  uint32
-	strsize uint32
-	str     []byte
-	sym     []ldMachoSym
-}
-
-type ldMachoSym struct {
-	name    string
-	type_   uint8
-	sectnum uint8
-	desc    uint16
-	kind    int8
-	value   uint64
-	sym     *sym.Symbol
-}
-
-type ldMachoDysymtab struct {
-	ilocalsym      uint32
-	nlocalsym      uint32
-	iextdefsym     uint32
-	nextdefsym     uint32
-	iundefsym      uint32
-	nundefsym      uint32
-	tocoff         uint32
-	ntoc           uint32
-	modtaboff      uint32
-	nmodtab        uint32
-	extrefsymoff   uint32
-	nextrefsyms    uint32
-	indirectsymoff uint32
-	nindirectsyms  uint32
-	extreloff      uint32
-	nextrel        uint32
-	locreloff      uint32
-	nlocrel        uint32
-	indir          []uint32
-}
-
-// ldMachoSym.type_
-const (
-	N_EXT  = 0x01
-	N_TYPE = 0x1e
-	N_STAB = 0xe0
-)
-
-// ldMachoSym.desc
-const (
-	N_WEAK_REF = 0x40
-	N_WEAK_DEF = 0x80
-)
-
-const (
-	LdMachoCpuVax         = 1
-	LdMachoCpu68000       = 6
-	LdMachoCpu386         = 7
-	LdMachoCpuAmd64       = 0x1000007
-	LdMachoCpuMips        = 8
-	LdMachoCpu98000       = 10
-	LdMachoCpuHppa        = 11
-	LdMachoCpuArm         = 12
-	LdMachoCpu88000       = 13
-	LdMachoCpuSparc       = 14
-	LdMachoCpu860         = 15
-	LdMachoCpuAlpha       = 16
-	LdMachoCpuPower       = 18
-	LdMachoCmdSegment     = 1
-	LdMachoCmdSymtab      = 2
-	LdMachoCmdSymseg      = 3
-	LdMachoCmdThread      = 4
-	LdMachoCmdDysymtab    = 11
-	LdMachoCmdSegment64   = 25
-	LdMachoFileObject     = 1
-	LdMachoFileExecutable = 2
-	LdMachoFileFvmlib     = 3
-	LdMachoFileCore       = 4
-	LdMachoFilePreload    = 5
-)
-
-func unpackcmd(p []byte, m *ldMachoObj, c *ldMachoCmd, type_ uint, sz uint) int {
-	e4 := m.e.Uint32
-	e8 := m.e.Uint64
-
-	c.type_ = int(type_)
-	c.size = uint32(sz)
-	switch type_ {
-	default:
-		return -1
-
-	case LdMachoCmdSegment:
-		if sz < 56 {
-			return -1
-		}
-		c.seg.name = cstring(p[8:24])
-		c.seg.vmaddr = uint64(e4(p[24:]))
-		c.seg.vmsize = uint64(e4(p[28:]))
-		c.seg.fileoff = e4(p[32:])
-		c.seg.filesz = e4(p[36:])
-		c.seg.maxprot = e4(p[40:])
-		c.seg.initprot = e4(p[44:])
-		c.seg.nsect = e4(p[48:])
-		c.seg.flags = e4(p[52:])
-		c.seg.sect = make([]ldMachoSect, c.seg.nsect)
-		if uint32(sz) < 56+c.seg.nsect*68 {
-			return -1
-		}
-		p = p[56:]
-		var s *ldMachoSect
-		for i := 0; uint32(i) < c.seg.nsect; i++ {
-			s = &c.seg.sect[i]
-			s.name = cstring(p[0:16])
-			s.segname = cstring(p[16:32])
-			s.addr = uint64(e4(p[32:]))
-			s.size = uint64(e4(p[36:]))
-			s.off = e4(p[40:])
-			s.align = e4(p[44:])
-			s.reloff = e4(p[48:])
-			s.nreloc = e4(p[52:])
-			s.flags = e4(p[56:])
-			s.res1 = e4(p[60:])
-			s.res2 = e4(p[64:])
-			p = p[68:]
-		}
-
-	case LdMachoCmdSegment64:
-		if sz < 72 {
-			return -1
-		}
-		c.seg.name = cstring(p[8:24])
-		c.seg.vmaddr = e8(p[24:])
-		c.seg.vmsize = e8(p[32:])
-		c.seg.fileoff = uint32(e8(p[40:]))
-		c.seg.filesz = uint32(e8(p[48:]))
-		c.seg.maxprot = e4(p[56:])
-		c.seg.initprot = e4(p[60:])
-		c.seg.nsect = e4(p[64:])
-		c.seg.flags = e4(p[68:])
-		c.seg.sect = make([]ldMachoSect, c.seg.nsect)
-		if uint32(sz) < 72+c.seg.nsect*80 {
-			return -1
-		}
-		p = p[72:]
-		var s *ldMachoSect
-		for i := 0; uint32(i) < c.seg.nsect; i++ {
-			s = &c.seg.sect[i]
-			s.name = cstring(p[0:16])
-			s.segname = cstring(p[16:32])
-			s.addr = e8(p[32:])
-			s.size = e8(p[40:])
-			s.off = e4(p[48:])
-			s.align = e4(p[52:])
-			s.reloff = e4(p[56:])
-			s.nreloc = e4(p[60:])
-			s.flags = e4(p[64:])
-			s.res1 = e4(p[68:])
-			s.res2 = e4(p[72:])
-
-			// p+76 is reserved
-			p = p[80:]
-		}
-
-	case LdMachoCmdSymtab:
-		if sz < 24 {
-			return -1
-		}
-		c.sym.symoff = e4(p[8:])
-		c.sym.nsym = e4(p[12:])
-		c.sym.stroff = e4(p[16:])
-		c.sym.strsize = e4(p[20:])
-
-	case LdMachoCmdDysymtab:
-		if sz < 80 {
-			return -1
-		}
-		c.dsym.ilocalsym = e4(p[8:])
-		c.dsym.nlocalsym = e4(p[12:])
-		c.dsym.iextdefsym = e4(p[16:])
-		c.dsym.nextdefsym = e4(p[20:])
-		c.dsym.iundefsym = e4(p[24:])
-		c.dsym.nundefsym = e4(p[28:])
-		c.dsym.tocoff = e4(p[32:])
-		c.dsym.ntoc = e4(p[36:])
-		c.dsym.modtaboff = e4(p[40:])
-		c.dsym.nmodtab = e4(p[44:])
-		c.dsym.extrefsymoff = e4(p[48:])
-		c.dsym.nextrefsyms = e4(p[52:])
-		c.dsym.indirectsymoff = e4(p[56:])
-		c.dsym.nindirectsyms = e4(p[60:])
-		c.dsym.extreloff = e4(p[64:])
-		c.dsym.nextrel = e4(p[68:])
-		c.dsym.locreloff = e4(p[72:])
-		c.dsym.nlocrel = e4(p[76:])
-	}
-
-	return 0
-}
-
-func macholoadrel(m *ldMachoObj, sect *ldMachoSect) int {
-	if sect.rel != nil || sect.nreloc == 0 {
-		return 0
-	}
-	rel := make([]ldMachoRel, sect.nreloc)
-	n := int(sect.nreloc * 8)
-	buf := make([]byte, n)
-	m.f.MustSeek(m.base+int64(sect.reloff), 0)
-	if _, err := io.ReadFull(m.f, buf); err != nil {
-		return -1
-	}
-	for i := uint32(0); i < sect.nreloc; i++ {
-		r := &rel[i]
-		p := buf[i*8:]
-		r.addr = m.e.Uint32(p)
-
-		// TODO(rsc): Wrong interpretation for big-endian bitfields?
-		if r.addr&0x80000000 != 0 {
-			// scatterbrained relocation
-			r.scattered = 1
-
-			v := r.addr >> 24
-			r.addr &= 0xFFFFFF
-			r.type_ = uint8(v & 0xF)
-			v >>= 4
-			r.length = 1 << (v & 3)
-			v >>= 2
-			r.pcrel = uint8(v & 1)
-			r.value = m.e.Uint32(p[4:])
-		} else {
-			v := m.e.Uint32(p[4:])
-			r.symnum = v & 0xFFFFFF
-			v >>= 24
-			r.pcrel = uint8(v & 1)
-			v >>= 1
-			r.length = 1 << (v & 3)
-			v >>= 2
-			r.extrn = uint8(v & 1)
-			v >>= 1
-			r.type_ = uint8(v)
-		}
-	}
-
-	sect.rel = rel
-	return 0
-}
-
-func macholoaddsym(m *ldMachoObj, d *ldMachoDysymtab) int {
-	n := int(d.nindirectsyms)
-
-	p := make([]byte, n*4)
-	m.f.MustSeek(m.base+int64(d.indirectsymoff), 0)
-	if _, err := io.ReadFull(m.f, p); err != nil {
-		return -1
-	}
-
-	d.indir = make([]uint32, n)
-	for i := 0; i < n; i++ {
-		d.indir[i] = m.e.Uint32(p[4*i:])
-	}
-	return 0
-}
-
-func macholoadsym(m *ldMachoObj, symtab *ldMachoSymtab) int {
-	if symtab.sym != nil {
-		return 0
-	}
-
-	strbuf := make([]byte, symtab.strsize)
-	m.f.MustSeek(m.base+int64(symtab.stroff), 0)
-	if _, err := io.ReadFull(m.f, strbuf); err != nil {
-		return -1
-	}
-
-	symsize := 12
-	if m.is64 {
-		symsize = 16
-	}
-	n := int(symtab.nsym * uint32(symsize))
-	symbuf := make([]byte, n)
-	m.f.MustSeek(m.base+int64(symtab.symoff), 0)
-	if _, err := io.ReadFull(m.f, symbuf); err != nil {
-		return -1
-	}
-	sym := make([]ldMachoSym, symtab.nsym)
-	p := symbuf
-	for i := uint32(0); i < symtab.nsym; i++ {
-		s := &sym[i]
-		v := m.e.Uint32(p)
-		if v >= symtab.strsize {
-			return -1
-		}
-		s.name = cstring(strbuf[v:])
-		s.type_ = p[4]
-		s.sectnum = p[5]
-		s.desc = m.e.Uint16(p[6:])
-		if m.is64 {
-			s.value = m.e.Uint64(p[8:])
-		} else {
-			s.value = uint64(m.e.Uint32(p[8:]))
-		}
-		p = p[symsize:]
-	}
-
-	symtab.str = strbuf
-	symtab.sym = sym
-	return 0
-}
-
-func Load(l *loader.Loader, arch *sys.Arch, syms *sym.Symbols, f *bio.Reader, pkg string, length int64, pn string) ([]*sym.Symbol, error) {
-	newSym := func(name string, version int) *sym.Symbol {
-		return l.LookupOrCreate(name, version, syms)
-	}
-	return load(arch, syms.IncVersion(), newSym, f, pkg, length, pn)
-}
-
-func LoadOld(arch *sys.Arch, syms *sym.Symbols, f *bio.Reader, pkg string, length int64, pn string) (textp []*sym.Symbol, err error) {
-	return load(arch, syms.IncVersion(), syms.Lookup, f, pkg, length, pn)
-}
-
-// load the Mach-O file pn from f.
-// Symbols are written into syms, and a slice of the text symbols is returned.
-func load(arch *sys.Arch, localSymVersion int, lookup func(string, int) *sym.Symbol, f *bio.Reader, pkg string, length int64, pn string) (textp []*sym.Symbol, err error) {
-	errorf := func(str string, args ...interface{}) ([]*sym.Symbol, error) {
-		return nil, fmt.Errorf("loadmacho: %v: %v", pn, fmt.Sprintf(str, args...))
-	}
-
-	base := f.Offset()
-
-	var hdr [7 * 4]uint8
-	if _, err := io.ReadFull(f, hdr[:]); err != nil {
-		return errorf("reading hdr: %v", err)
-	}
-
-	var e binary.ByteOrder
-	if binary.BigEndian.Uint32(hdr[:])&^1 == 0xFEEDFACE {
-		e = binary.BigEndian
-	} else if binary.LittleEndian.Uint32(hdr[:])&^1 == 0xFEEDFACE {
-		e = binary.LittleEndian
-	} else {
-		return errorf("bad magic - not mach-o file")
-	}
-
-	is64 := e.Uint32(hdr[:]) == 0xFEEDFACF
-	ncmd := e.Uint32(hdr[4*4:])
-	cmdsz := e.Uint32(hdr[5*4:])
-	if ncmd > 0x10000 || cmdsz >= 0x01000000 {
-		return errorf("implausible mach-o header ncmd=%d cmdsz=%d", ncmd, cmdsz)
-	}
-
-	if is64 {
-		f.MustSeek(4, 1) // skip reserved word in header
-	}
-
-	m := &ldMachoObj{
-		f:          f,
-		e:          e,
-		cputype:    uint(e.Uint32(hdr[1*4:])),
-		subcputype: uint(e.Uint32(hdr[2*4:])),
-		filetype:   e.Uint32(hdr[3*4:]),
-		ncmd:       uint(ncmd),
-		flags:      e.Uint32(hdr[6*4:]),
-		is64:       is64,
-		base:       base,
-		length:     length,
-		name:       pn,
-	}
-
-	switch arch.Family {
-	default:
-		return errorf("mach-o %s unimplemented", arch.Name)
-
-	case sys.AMD64:
-		if e != binary.LittleEndian || m.cputype != LdMachoCpuAmd64 {
-			return errorf("mach-o object but not amd64")
-		}
-	}
-
-	m.cmd = make([]ldMachoCmd, ncmd)
-	cmdp := make([]byte, cmdsz)
-	if _, err := io.ReadFull(f, cmdp); err != nil {
-		return errorf("reading cmds: %v", err)
-	}
-
-	// read and parse load commands
-	var c *ldMachoCmd
-
-	var symtab *ldMachoSymtab
-	var dsymtab *ldMachoDysymtab
-
-	off := uint32(len(hdr))
-	for i := uint32(0); i < ncmd; i++ {
-		ty := e.Uint32(cmdp)
-		sz := e.Uint32(cmdp[4:])
-		m.cmd[i].off = off
-		unpackcmd(cmdp, m, &m.cmd[i], uint(ty), uint(sz))
-		cmdp = cmdp[sz:]
-		off += sz
-		if ty == LdMachoCmdSymtab {
-			if symtab != nil {
-				return errorf("multiple symbol tables")
-			}
-
-			symtab = &m.cmd[i].sym
-			macholoadsym(m, symtab)
-		}
-
-		if ty == LdMachoCmdDysymtab {
-			dsymtab = &m.cmd[i].dsym
-			macholoaddsym(m, dsymtab)
-		}
-
-		if (is64 && ty == LdMachoCmdSegment64) || (!is64 && ty == LdMachoCmdSegment) {
-			if c != nil {
-				return errorf("multiple load commands")
-			}
-
-			c = &m.cmd[i]
-		}
-	}
-
-	// load text and data segments into memory.
-	// they are not as small as the load commands, but we'll need
-	// the memory anyway for the symbol images, so we might
-	// as well use one large chunk.
-	if c == nil {
-		return errorf("no load command")
-	}
-
-	if symtab == nil {
-		// our work is done here - no symbols means nothing can refer to this file
-		return
-	}
-
-	if int64(c.seg.fileoff+c.seg.filesz) >= length {
-		return errorf("load segment out of range")
-	}
-
-	f.MustSeek(m.base+int64(c.seg.fileoff), 0)
-	dat := make([]byte, c.seg.filesz)
-	if _, err := io.ReadFull(f, dat); err != nil {
-		return errorf("cannot load object data: %v", err)
-	}
-
-	for i := uint32(0); i < c.seg.nsect; i++ {
-		sect := &c.seg.sect[i]
-		if sect.segname != "__TEXT" && sect.segname != "__DATA" {
-			continue
-		}
-		if sect.name == "__eh_frame" {
-			continue
-		}
-		name := fmt.Sprintf("%s(%s/%s)", pkg, sect.segname, sect.name)
-		s := lookup(name, localSymVersion)
-		if s.Type != 0 {
-			return errorf("duplicate %s/%s", sect.segname, sect.name)
-		}
-
-		if sect.flags&0xff == 1 { // S_ZEROFILL
-			s.P = make([]byte, sect.size)
-		} else {
-			s.P = dat[sect.addr-c.seg.vmaddr:][:sect.size]
-		}
-		s.Size = int64(len(s.P))
-
-		if sect.segname == "__TEXT" {
-			if sect.name == "__text" {
-				s.Type = sym.STEXT
-			} else {
-				s.Type = sym.SRODATA
-			}
-		} else {
-			if sect.name == "__bss" {
-				s.Type = sym.SNOPTRBSS
-				s.P = s.P[:0]
-			} else {
-				s.Type = sym.SNOPTRDATA
-			}
-		}
-
-		sect.sym = s
-	}
-
-	// enter sub-symbols into symbol table.
-	// have to guess sizes from next symbol.
-	for i := uint32(0); i < symtab.nsym; i++ {
-		machsym := &symtab.sym[i]
-		if machsym.type_&N_STAB != 0 {
-			continue
-		}
-
-		// TODO: check sym->type against outer->type.
-		name := machsym.name
-
-		if name[0] == '_' && name[1] != '\x00' {
-			name = name[1:]
-		}
-		v := 0
-		if machsym.type_&N_EXT == 0 {
-			v = localSymVersion
-		}
-		s := lookup(name, v)
-		if machsym.type_&N_EXT == 0 {
-			s.Attr |= sym.AttrDuplicateOK
-		}
-		if machsym.desc&(N_WEAK_REF|N_WEAK_DEF) != 0 {
-			s.Attr |= sym.AttrDuplicateOK
-		}
-		machsym.sym = s
-		if machsym.sectnum == 0 { // undefined
-			continue
-		}
-		if uint32(machsym.sectnum) > c.seg.nsect {
-			return errorf("reference to invalid section %d", machsym.sectnum)
-		}
-
-		sect := &c.seg.sect[machsym.sectnum-1]
-		outer := sect.sym
-		if outer == nil {
-			continue // ignore reference to invalid section
-		}
-
-		if s.Outer != nil {
-			if s.Attr.DuplicateOK() {
-				continue
-			}
-			return errorf("duplicate symbol reference: %s in both %s and %s", s.Name, s.Outer.Name, sect.sym.Name)
-		}
-
-		s.Type = outer.Type
-		s.Attr |= sym.AttrSubSymbol
-		s.Sub = outer.Sub
-		outer.Sub = s
-		s.Outer = outer
-		s.Value = int64(machsym.value - sect.addr)
-		if !s.Attr.CgoExportDynamic() {
-			s.SetDynimplib("") // satisfy dynimport
-		}
-		if outer.Type == sym.STEXT {
-			if s.Attr.External() && !s.Attr.DuplicateOK() {
-				return errorf("%v: duplicate symbol definition", s)
-			}
-			s.Attr |= sym.AttrExternal
-		}
-
-		machsym.sym = s
-	}
-
-	// Sort outer lists by address, adding to textp.
-	// This keeps textp in increasing address order.
-	for i := 0; uint32(i) < c.seg.nsect; i++ {
-		sect := &c.seg.sect[i]
-		s := sect.sym
-		if s == nil {
-			continue
-		}
-		if s.Sub != nil {
-			s.Sub = sym.SortSub(s.Sub)
-
-			// assign sizes, now that we know symbols in sorted order.
-			for s1 := s.Sub; s1 != nil; s1 = s1.Sub {
-				if s1.Sub != nil {
-					s1.Size = s1.Sub.Value - s1.Value
-				} else {
-					s1.Size = s.Value + s.Size - s1.Value
-				}
-			}
-		}
-
-		if s.Type == sym.STEXT {
-			if s.Attr.OnList() {
-				return errorf("symbol %s listed multiple times", s.Name)
-			}
-			s.Attr |= sym.AttrOnList
-			textp = append(textp, s)
-			for s1 := s.Sub; s1 != nil; s1 = s1.Sub {
-				if s1.Attr.OnList() {
-					return errorf("symbol %s listed multiple times", s1.Name)
-				}
-				s1.Attr |= sym.AttrOnList
-				textp = append(textp, s1)
-			}
-		}
-	}
-
-	// load relocations
-	for i := 0; uint32(i) < c.seg.nsect; i++ {
-		sect := &c.seg.sect[i]
-		s := sect.sym
-		if s == nil {
-			continue
-		}
-		macholoadrel(m, sect)
-		if sect.rel == nil {
-			continue
-		}
-		r := make([]sym.Reloc, sect.nreloc)
-		rpi := 0
-		for j := uint32(0); j < sect.nreloc; j++ {
-			rp := &r[rpi]
-			rel := &sect.rel[j]
-			if rel.scattered != 0 {
-				// mach-o only uses scattered relocation on 32-bit platforms,
-				// which are no longer supported.
-				return errorf("%v: unexpected scattered relocation", s)
-			}
-
-			rp.Siz = rel.length
-			rp.Type = objabi.MachoRelocOffset + (objabi.RelocType(rel.type_) << 1) + objabi.RelocType(rel.pcrel)
-			rp.Off = int32(rel.addr)
-
-			// Handle X86_64_RELOC_SIGNED referencing a section (rel->extrn == 0).
-			if arch.Family == sys.AMD64 && rel.extrn == 0 && rel.type_ == MACHO_X86_64_RELOC_SIGNED {
-				// Calculate the addend as the offset into the section.
-				//
-				// The rip-relative offset stored in the object file is encoded
-				// as follows:
-				//
-				//    movsd	0x00000360(%rip),%xmm0
-				//
-				// To get the absolute address of the value this rip-relative address is pointing
-				// to, we must add the address of the next instruction to it. This is done by
-				// taking the address of the relocation and adding 4 to it (since the rip-relative
-				// offset can at most be 32 bits long).  To calculate the offset into the section the
-				// relocation is referencing, we subtract the vaddr of the start of the referenced
-				// section found in the original object file.
-				//
-				// [For future reference, see Darwin's /usr/include/mach-o/x86_64/reloc.h]
-				secaddr := c.seg.sect[rel.symnum-1].addr
-
-				rp.Add = int64(uint64(int64(int32(e.Uint32(s.P[rp.Off:])))+int64(rp.Off)+4) - secaddr)
-			} else {
-				rp.Add = int64(int32(e.Uint32(s.P[rp.Off:])))
-			}
-
-			// An unsigned internal relocation has a value offset
-			// by the section address.
-			if arch.Family == sys.AMD64 && rel.extrn == 0 && rel.type_ == MACHO_X86_64_RELOC_UNSIGNED {
-				secaddr := c.seg.sect[rel.symnum-1].addr
-				rp.Add -= int64(secaddr)
-			}
-
-			if rel.extrn == 0 {
-				if rel.symnum < 1 || rel.symnum > c.seg.nsect {
-					return errorf("invalid relocation: section reference out of range %d vs %d", rel.symnum, c.seg.nsect)
-				}
-
-				rp.Sym = c.seg.sect[rel.symnum-1].sym
-				if rp.Sym == nil {
-					return errorf("invalid relocation: %s", c.seg.sect[rel.symnum-1].name)
-				}
-			} else {
-				if rel.symnum >= symtab.nsym {
-					return errorf("invalid relocation: symbol reference out of range")
-				}
-
-				rp.Sym = symtab.sym[rel.symnum].sym
-			}
-
-			rpi++
-		}
-
-		sort.Sort(sym.RelocByOff(r[:rpi]))
-		s.R = r
-		s.R = s.R[:rpi]
-	}
-
-	return textp, nil
-}
-
-func cstring(x []byte) string {
-	i := bytes.IndexByte(x, '\x00')
-	if i >= 0 {
-		x = x[:i]
-	}
-	return string(x)
-}
diff --git a/src/cmd/oldlink/internal/loadpe/ldpe.go b/src/cmd/oldlink/internal/loadpe/ldpe.go
deleted file mode 100644
index f7df774..0000000
--- a/src/cmd/oldlink/internal/loadpe/ldpe.go
+++ /dev/null
@@ -1,513 +0,0 @@
-// Copyright 2010 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 loadpe implements a PE/COFF file reader.
-package loadpe
-
-import (
-	"cmd/internal/bio"
-	"cmd/internal/objabi"
-	"cmd/internal/sys"
-	"cmd/oldlink/internal/loader"
-	"cmd/oldlink/internal/sym"
-	"debug/pe"
-	"encoding/binary"
-	"errors"
-	"fmt"
-	"io"
-	"sort"
-	"strings"
-)
-
-const (
-	// TODO: the Microsoft doco says IMAGE_SYM_DTYPE_ARRAY is 3 (same with IMAGE_SYM_DTYPE_POINTER and IMAGE_SYM_DTYPE_FUNCTION)
-	IMAGE_SYM_UNDEFINED              = 0
-	IMAGE_SYM_ABSOLUTE               = -1
-	IMAGE_SYM_DEBUG                  = -2
-	IMAGE_SYM_TYPE_NULL              = 0
-	IMAGE_SYM_TYPE_VOID              = 1
-	IMAGE_SYM_TYPE_CHAR              = 2
-	IMAGE_SYM_TYPE_SHORT             = 3
-	IMAGE_SYM_TYPE_INT               = 4
-	IMAGE_SYM_TYPE_LONG              = 5
-	IMAGE_SYM_TYPE_FLOAT             = 6
-	IMAGE_SYM_TYPE_DOUBLE            = 7
-	IMAGE_SYM_TYPE_STRUCT            = 8
-	IMAGE_SYM_TYPE_UNION             = 9
-	IMAGE_SYM_TYPE_ENUM              = 10
-	IMAGE_SYM_TYPE_MOE               = 11
-	IMAGE_SYM_TYPE_BYTE              = 12
-	IMAGE_SYM_TYPE_WORD              = 13
-	IMAGE_SYM_TYPE_UINT              = 14
-	IMAGE_SYM_TYPE_DWORD             = 15
-	IMAGE_SYM_TYPE_PCODE             = 32768
-	IMAGE_SYM_DTYPE_NULL             = 0
-	IMAGE_SYM_DTYPE_POINTER          = 0x10
-	IMAGE_SYM_DTYPE_FUNCTION         = 0x20
-	IMAGE_SYM_DTYPE_ARRAY            = 0x30
-	IMAGE_SYM_CLASS_END_OF_FUNCTION  = -1
-	IMAGE_SYM_CLASS_NULL             = 0
-	IMAGE_SYM_CLASS_AUTOMATIC        = 1
-	IMAGE_SYM_CLASS_EXTERNAL         = 2
-	IMAGE_SYM_CLASS_STATIC           = 3
-	IMAGE_SYM_CLASS_REGISTER         = 4
-	IMAGE_SYM_CLASS_EXTERNAL_DEF     = 5
-	IMAGE_SYM_CLASS_LABEL            = 6
-	IMAGE_SYM_CLASS_UNDEFINED_LABEL  = 7
-	IMAGE_SYM_CLASS_MEMBER_OF_STRUCT = 8
-	IMAGE_SYM_CLASS_ARGUMENT         = 9
-	IMAGE_SYM_CLASS_STRUCT_TAG       = 10
-	IMAGE_SYM_CLASS_MEMBER_OF_UNION  = 11
-	IMAGE_SYM_CLASS_UNION_TAG        = 12
-	IMAGE_SYM_CLASS_TYPE_DEFINITION  = 13
-	IMAGE_SYM_CLASS_UNDEFINED_STATIC = 14
-	IMAGE_SYM_CLASS_ENUM_TAG         = 15
-	IMAGE_SYM_CLASS_MEMBER_OF_ENUM   = 16
-	IMAGE_SYM_CLASS_REGISTER_PARAM   = 17
-	IMAGE_SYM_CLASS_BIT_FIELD        = 18
-	IMAGE_SYM_CLASS_FAR_EXTERNAL     = 68 /* Not in PECOFF v8 spec */
-	IMAGE_SYM_CLASS_BLOCK            = 100
-	IMAGE_SYM_CLASS_FUNCTION         = 101
-	IMAGE_SYM_CLASS_END_OF_STRUCT    = 102
-	IMAGE_SYM_CLASS_FILE             = 103
-	IMAGE_SYM_CLASS_SECTION          = 104
-	IMAGE_SYM_CLASS_WEAK_EXTERNAL    = 105
-	IMAGE_SYM_CLASS_CLR_TOKEN        = 107
-	IMAGE_REL_I386_ABSOLUTE          = 0x0000
-	IMAGE_REL_I386_DIR16             = 0x0001
-	IMAGE_REL_I386_REL16             = 0x0002
-	IMAGE_REL_I386_DIR32             = 0x0006
-	IMAGE_REL_I386_DIR32NB           = 0x0007
-	IMAGE_REL_I386_SEG12             = 0x0009
-	IMAGE_REL_I386_SECTION           = 0x000A
-	IMAGE_REL_I386_SECREL            = 0x000B
-	IMAGE_REL_I386_TOKEN             = 0x000C
-	IMAGE_REL_I386_SECREL7           = 0x000D
-	IMAGE_REL_I386_REL32             = 0x0014
-	IMAGE_REL_AMD64_ABSOLUTE         = 0x0000
-	IMAGE_REL_AMD64_ADDR64           = 0x0001
-	IMAGE_REL_AMD64_ADDR32           = 0x0002
-	IMAGE_REL_AMD64_ADDR32NB         = 0x0003
-	IMAGE_REL_AMD64_REL32            = 0x0004
-	IMAGE_REL_AMD64_REL32_1          = 0x0005
-	IMAGE_REL_AMD64_REL32_2          = 0x0006
-	IMAGE_REL_AMD64_REL32_3          = 0x0007
-	IMAGE_REL_AMD64_REL32_4          = 0x0008
-	IMAGE_REL_AMD64_REL32_5          = 0x0009
-	IMAGE_REL_AMD64_SECTION          = 0x000A
-	IMAGE_REL_AMD64_SECREL           = 0x000B
-	IMAGE_REL_AMD64_SECREL7          = 0x000C
-	IMAGE_REL_AMD64_TOKEN            = 0x000D
-	IMAGE_REL_AMD64_SREL32           = 0x000E
-	IMAGE_REL_AMD64_PAIR             = 0x000F
-	IMAGE_REL_AMD64_SSPAN32          = 0x0010
-	IMAGE_REL_ARM_ABSOLUTE           = 0x0000
-	IMAGE_REL_ARM_ADDR32             = 0x0001
-	IMAGE_REL_ARM_ADDR32NB           = 0x0002
-	IMAGE_REL_ARM_BRANCH24           = 0x0003
-	IMAGE_REL_ARM_BRANCH11           = 0x0004
-	IMAGE_REL_ARM_SECTION            = 0x000E
-	IMAGE_REL_ARM_SECREL             = 0x000F
-	IMAGE_REL_ARM_MOV32              = 0x0010
-	IMAGE_REL_THUMB_MOV32            = 0x0011
-	IMAGE_REL_THUMB_BRANCH20         = 0x0012
-	IMAGE_REL_THUMB_BRANCH24         = 0x0014
-	IMAGE_REL_THUMB_BLX23            = 0x0015
-	IMAGE_REL_ARM_PAIR               = 0x0016
-)
-
-// TODO(crawshaw): de-duplicate these symbols with cmd/internal/ld, ideally in debug/pe.
-const (
-	IMAGE_SCN_CNT_CODE               = 0x00000020
-	IMAGE_SCN_CNT_INITIALIZED_DATA   = 0x00000040
-	IMAGE_SCN_CNT_UNINITIALIZED_DATA = 0x00000080
-	IMAGE_SCN_MEM_DISCARDABLE        = 0x02000000
-	IMAGE_SCN_MEM_EXECUTE            = 0x20000000
-	IMAGE_SCN_MEM_READ               = 0x40000000
-	IMAGE_SCN_MEM_WRITE              = 0x80000000
-)
-
-// TODO(brainman): maybe just add ReadAt method to bio.Reader instead of creating peBiobuf
-
-// peBiobuf makes bio.Reader look like io.ReaderAt.
-type peBiobuf bio.Reader
-
-func (f *peBiobuf) ReadAt(p []byte, off int64) (int, error) {
-	ret := ((*bio.Reader)(f)).MustSeek(off, 0)
-	if ret < 0 {
-		return 0, errors.New("fail to seek")
-	}
-	n, err := f.Read(p)
-	if err != nil {
-		return 0, err
-	}
-	return n, nil
-}
-
-func Load(l *loader.Loader, arch *sys.Arch, syms *sym.Symbols, input *bio.Reader, pkg string, length int64, pn string) (textp []*sym.Symbol, rsrc *sym.Symbol, err error) {
-	lookup := func(name string, version int) *sym.Symbol {
-		return l.LookupOrCreate(name, version, syms)
-	}
-	return load(arch, lookup, syms.IncVersion(), input, pkg, length, pn)
-}
-
-func LoadOld(arch *sys.Arch, syms *sym.Symbols, input *bio.Reader, pkg string, length int64, pn string) (textp []*sym.Symbol, rsrc *sym.Symbol, err error) {
-	return load(arch, syms.Lookup, syms.IncVersion(), input, pkg, length, pn)
-}
-
-// load loads the PE file pn from input.
-// Symbols are written into syms, and a slice of the text symbols is returned.
-// If an .rsrc section is found, its symbol is returned as rsrc.
-func load(arch *sys.Arch, lookup func(string, int) *sym.Symbol, localSymVersion int, input *bio.Reader, pkg string, length int64, pn string) (textp []*sym.Symbol, rsrc *sym.Symbol, err error) {
-	sectsyms := make(map[*pe.Section]*sym.Symbol)
-	sectdata := make(map[*pe.Section][]byte)
-
-	// Some input files are archives containing multiple of
-	// object files, and pe.NewFile seeks to the start of
-	// input file and get confused. Create section reader
-	// to stop pe.NewFile looking before current position.
-	sr := io.NewSectionReader((*peBiobuf)(input), input.Offset(), 1<<63-1)
-
-	// TODO: replace pe.NewFile with pe.Load (grep for "add Load function" in debug/pe for details)
-	f, err := pe.NewFile(sr)
-	if err != nil {
-		return nil, nil, err
-	}
-	defer f.Close()
-
-	// TODO return error if found .cormeta
-
-	// create symbols for mapped sections
-	for _, sect := range f.Sections {
-		if sect.Characteristics&IMAGE_SCN_MEM_DISCARDABLE != 0 {
-			continue
-		}
-
-		if sect.Characteristics&(IMAGE_SCN_CNT_CODE|IMAGE_SCN_CNT_INITIALIZED_DATA|IMAGE_SCN_CNT_UNINITIALIZED_DATA) == 0 {
-			// This has been seen for .idata sections, which we
-			// want to ignore. See issues 5106 and 5273.
-			continue
-		}
-
-		name := fmt.Sprintf("%s(%s)", pkg, sect.Name)
-		s := lookup(name, localSymVersion)
-
-		switch sect.Characteristics & (IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE) {
-		case IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ: //.rdata
-			s.Type = sym.SRODATA
-
-		case IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE: //.bss
-			s.Type = sym.SNOPTRBSS
-
-		case IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE: //.data
-			s.Type = sym.SNOPTRDATA
-
-		case IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ: //.text
-			s.Type = sym.STEXT
-
-		default:
-			return nil, nil, fmt.Errorf("unexpected flags %#06x for PE section %s", sect.Characteristics, sect.Name)
-		}
-
-		if s.Type != sym.SNOPTRBSS {
-			data, err := sect.Data()
-			if err != nil {
-				return nil, nil, err
-			}
-			sectdata[sect] = data
-			s.P = data
-		}
-		s.Size = int64(sect.Size)
-		sectsyms[sect] = s
-		if sect.Name == ".rsrc" {
-			rsrc = s
-		}
-	}
-
-	// load relocations
-	for _, rsect := range f.Sections {
-		if _, found := sectsyms[rsect]; !found {
-			continue
-		}
-		if rsect.NumberOfRelocations == 0 {
-			continue
-		}
-		if rsect.Characteristics&IMAGE_SCN_MEM_DISCARDABLE != 0 {
-			continue
-		}
-		if rsect.Characteristics&(IMAGE_SCN_CNT_CODE|IMAGE_SCN_CNT_INITIALIZED_DATA|IMAGE_SCN_CNT_UNINITIALIZED_DATA) == 0 {
-			// This has been seen for .idata sections, which we
-			// want to ignore. See issues 5106 and 5273.
-			continue
-		}
-
-		rs := make([]sym.Reloc, rsect.NumberOfRelocations)
-		for j, r := range rsect.Relocs {
-			rp := &rs[j]
-			if int(r.SymbolTableIndex) >= len(f.COFFSymbols) {
-				return nil, nil, fmt.Errorf("relocation number %d symbol index idx=%d cannot be large then number of symbols %d", j, r.SymbolTableIndex, len(f.COFFSymbols))
-			}
-			pesym := &f.COFFSymbols[r.SymbolTableIndex]
-			gosym, err := readpesym(arch, lookup, f, pesym, sectsyms, localSymVersion)
-			if err != nil {
-				return nil, nil, err
-			}
-			if gosym == nil {
-				name, err := pesym.FullName(f.StringTable)
-				if err != nil {
-					name = string(pesym.Name[:])
-				}
-				return nil, nil, fmt.Errorf("reloc of invalid sym %s idx=%d type=%d", name, r.SymbolTableIndex, pesym.Type)
-			}
-
-			rp.Sym = gosym
-			rp.Siz = 4
-			rp.Off = int32(r.VirtualAddress)
-			switch arch.Family {
-			default:
-				return nil, nil, fmt.Errorf("%s: unsupported arch %v", pn, arch.Family)
-			case sys.I386, sys.AMD64:
-				switch r.Type {
-				default:
-					return nil, nil, fmt.Errorf("%s: %v: unknown relocation type %v", pn, sectsyms[rsect], r.Type)
-
-				case IMAGE_REL_I386_REL32, IMAGE_REL_AMD64_REL32,
-					IMAGE_REL_AMD64_ADDR32, // R_X86_64_PC32
-					IMAGE_REL_AMD64_ADDR32NB:
-					rp.Type = objabi.R_PCREL
-
-					rp.Add = int64(int32(binary.LittleEndian.Uint32(sectdata[rsect][rp.Off:])))
-
-				case IMAGE_REL_I386_DIR32NB, IMAGE_REL_I386_DIR32:
-					rp.Type = objabi.R_ADDR
-
-					// load addend from image
-					rp.Add = int64(int32(binary.LittleEndian.Uint32(sectdata[rsect][rp.Off:])))
-
-				case IMAGE_REL_AMD64_ADDR64: // R_X86_64_64
-					rp.Siz = 8
-
-					rp.Type = objabi.R_ADDR
-
-					// load addend from image
-					rp.Add = int64(binary.LittleEndian.Uint64(sectdata[rsect][rp.Off:]))
-				}
-
-			case sys.ARM:
-				switch r.Type {
-				default:
-					return nil, nil, fmt.Errorf("%s: %v: unknown ARM relocation type %v", pn, sectsyms[rsect], r.Type)
-
-				case IMAGE_REL_ARM_SECREL:
-					rp.Type = objabi.R_PCREL
-
-					rp.Add = int64(int32(binary.LittleEndian.Uint32(sectdata[rsect][rp.Off:])))
-
-				case IMAGE_REL_ARM_ADDR32:
-					rp.Type = objabi.R_ADDR
-
-					rp.Add = int64(int32(binary.LittleEndian.Uint32(sectdata[rsect][rp.Off:])))
-
-				case IMAGE_REL_ARM_BRANCH24:
-					rp.Type = objabi.R_CALLARM
-
-					rp.Add = int64(int32(binary.LittleEndian.Uint32(sectdata[rsect][rp.Off:])))
-				}
-			}
-
-			// ld -r could generate multiple section symbols for the
-			// same section but with different values, we have to take
-			// that into account
-			if issect(pesym) {
-				rp.Add += int64(pesym.Value)
-			}
-		}
-
-		sort.Sort(sym.RelocByOff(rs[:rsect.NumberOfRelocations]))
-
-		s := sectsyms[rsect]
-		s.R = rs
-		s.R = s.R[:rsect.NumberOfRelocations]
-	}
-
-	// enter sub-symbols into symbol table.
-	for i, numaux := 0, 0; i < len(f.COFFSymbols); i += numaux + 1 {
-		pesym := &f.COFFSymbols[i]
-
-		numaux = int(pesym.NumberOfAuxSymbols)
-
-		name, err := pesym.FullName(f.StringTable)
-		if err != nil {
-			return nil, nil, err
-		}
-		if name == "" {
-			continue
-		}
-		if issect(pesym) {
-			continue
-		}
-		if int(pesym.SectionNumber) > len(f.Sections) {
-			continue
-		}
-		if pesym.SectionNumber == IMAGE_SYM_DEBUG {
-			continue
-		}
-		var sect *pe.Section
-		if pesym.SectionNumber > 0 {
-			sect = f.Sections[pesym.SectionNumber-1]
-			if _, found := sectsyms[sect]; !found {
-				continue
-			}
-		}
-
-		s, err := readpesym(arch, lookup, f, pesym, sectsyms, localSymVersion)
-		if err != nil {
-			return nil, nil, err
-		}
-
-		if pesym.SectionNumber == 0 { // extern
-			if s.Type == sym.SDYNIMPORT {
-				s.SetPlt(-2) // flag for dynimport in PE object files.
-			}
-			if s.Type == sym.SXREF && pesym.Value > 0 { // global data
-				s.Type = sym.SNOPTRDATA
-				s.Size = int64(pesym.Value)
-			}
-
-			continue
-		} else if pesym.SectionNumber > 0 && int(pesym.SectionNumber) <= len(f.Sections) {
-			sect = f.Sections[pesym.SectionNumber-1]
-			if _, found := sectsyms[sect]; !found {
-				return nil, nil, fmt.Errorf("%s: %v: missing sect.sym", pn, s)
-			}
-		} else {
-			return nil, nil, fmt.Errorf("%s: %v: sectnum < 0!", pn, s)
-		}
-
-		if sect == nil {
-			return nil, rsrc, nil
-		}
-
-		if s.Outer != nil {
-			if s.Attr.DuplicateOK() {
-				continue
-			}
-			return nil, nil, fmt.Errorf("%s: duplicate symbol reference: %s in both %s and %s", pn, s.Name, s.Outer.Name, sectsyms[sect].Name)
-		}
-
-		sectsym := sectsyms[sect]
-		s.Sub = sectsym.Sub
-		sectsym.Sub = s
-		s.Type = sectsym.Type
-		s.Attr |= sym.AttrSubSymbol
-		s.Value = int64(pesym.Value)
-		s.Size = 4
-		s.Outer = sectsym
-		if sectsym.Type == sym.STEXT {
-			if s.Attr.External() && !s.Attr.DuplicateOK() {
-				return nil, nil, fmt.Errorf("%s: duplicate symbol definition", s.Name)
-			}
-			s.Attr |= sym.AttrExternal
-		}
-	}
-
-	// Sort outer lists by address, adding to textp.
-	// This keeps textp in increasing address order.
-	for _, sect := range f.Sections {
-		s := sectsyms[sect]
-		if s == nil {
-			continue
-		}
-		if s.Sub != nil {
-			s.Sub = sym.SortSub(s.Sub)
-		}
-		if s.Type == sym.STEXT {
-			if s.Attr.OnList() {
-				return nil, nil, fmt.Errorf("symbol %s listed multiple times", s.Name)
-			}
-			s.Attr |= sym.AttrOnList
-			textp = append(textp, s)
-			for s = s.Sub; s != nil; s = s.Sub {
-				if s.Attr.OnList() {
-					return nil, nil, fmt.Errorf("symbol %s listed multiple times", s.Name)
-				}
-				s.Attr |= sym.AttrOnList
-				textp = append(textp, s)
-			}
-		}
-	}
-
-	return textp, rsrc, nil
-}
-
-func issect(s *pe.COFFSymbol) bool {
-	return s.StorageClass == IMAGE_SYM_CLASS_STATIC && s.Type == 0 && s.Name[0] == '.'
-}
-
-func readpesym(arch *sys.Arch, lookup func(string, int) *sym.Symbol, f *pe.File, pesym *pe.COFFSymbol, sectsyms map[*pe.Section]*sym.Symbol, localSymVersion int) (*sym.Symbol, error) {
-	symname, err := pesym.FullName(f.StringTable)
-	if err != nil {
-		return nil, err
-	}
-	var name string
-	if issect(pesym) {
-		name = sectsyms[f.Sections[pesym.SectionNumber-1]].Name
-	} else {
-		name = symname
-		switch arch.Family {
-		case sys.AMD64:
-			if name == "__imp___acrt_iob_func" {
-				// Do not rename __imp___acrt_iob_func into __acrt_iob_func,
-				// because __imp___acrt_iob_func symbol is real
-				// (see commit b295099 from git://git.code.sf.net/p/mingw-w64/mingw-w64 for details).
-			} else {
-				name = strings.TrimPrefix(name, "__imp_") // __imp_Name => Name
-			}
-		case sys.I386:
-			if name == "__imp____acrt_iob_func" {
-				// Do not rename __imp____acrt_iob_func into ___acrt_iob_func,
-				// because __imp____acrt_iob_func symbol is real
-				// (see commit b295099 from git://git.code.sf.net/p/mingw-w64/mingw-w64 for details).
-			} else {
-				name = strings.TrimPrefix(name, "__imp_") // __imp_Name => Name
-			}
-			if name[0] == '_' {
-				name = name[1:] // _Name => Name
-			}
-		}
-	}
-
-	// remove last @XXX
-	if i := strings.LastIndex(name, "@"); i >= 0 {
-		name = name[:i]
-	}
-
-	var s *sym.Symbol
-	switch pesym.Type {
-	default:
-		return nil, fmt.Errorf("%s: invalid symbol type %d", symname, pesym.Type)
-
-	case IMAGE_SYM_DTYPE_FUNCTION, IMAGE_SYM_DTYPE_NULL:
-		switch pesym.StorageClass {
-		case IMAGE_SYM_CLASS_EXTERNAL: //global
-			s = lookup(name, 0)
-
-		case IMAGE_SYM_CLASS_NULL, IMAGE_SYM_CLASS_STATIC, IMAGE_SYM_CLASS_LABEL:
-			s = lookup(name, localSymVersion)
-			s.Attr |= sym.AttrDuplicateOK
-
-		default:
-			return nil, fmt.Errorf("%s: invalid symbol binding %d", symname, pesym.StorageClass)
-		}
-	}
-
-	if s != nil && s.Type == 0 && (pesym.StorageClass != IMAGE_SYM_CLASS_STATIC || pesym.Value != 0) {
-		s.Type = sym.SXREF
-	}
-	if strings.HasPrefix(symname, "__imp_") {
-		s.SetGot(-2) // flag for __imp_
-	}
-
-	return s, nil
-}
diff --git a/src/cmd/oldlink/internal/loadxcoff/ldxcoff.go b/src/cmd/oldlink/internal/loadxcoff/ldxcoff.go
deleted file mode 100644
index 832b168..0000000
--- a/src/cmd/oldlink/internal/loadxcoff/ldxcoff.go
+++ /dev/null
@@ -1,238 +0,0 @@
-// Copyright 2018 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 loadxcoff implements a XCOFF file reader.
-package loadxcoff
-
-import (
-	"cmd/internal/bio"
-	"cmd/internal/objabi"
-	"cmd/internal/sys"
-	"cmd/oldlink/internal/loader"
-	"cmd/oldlink/internal/sym"
-	"errors"
-	"fmt"
-	"internal/xcoff"
-)
-
-// ldSection is an XCOFF section with its symbols.
-type ldSection struct {
-	xcoff.Section
-	sym *sym.Symbol
-}
-
-// TODO(brainman): maybe just add ReadAt method to bio.Reader instead of creating xcoffBiobuf
-
-// xcoffBiobuf makes bio.Reader look like io.ReaderAt.
-type xcoffBiobuf bio.Reader
-
-func (f *xcoffBiobuf) ReadAt(p []byte, off int64) (int, error) {
-	ret := ((*bio.Reader)(f)).MustSeek(off, 0)
-	if ret < 0 {
-		return 0, errors.New("fail to seek")
-	}
-	n, err := f.Read(p)
-	if err != nil {
-		return 0, err
-	}
-	return n, nil
-}
-
-// Load loads xcoff files with the indexed object files.
-func Load(l *loader.Loader, arch *sys.Arch, syms *sym.Symbols, input *bio.Reader, pkg string, length int64, pn string) (textp []*sym.Symbol, err error) {
-	lookup := func(name string, version int) *sym.Symbol {
-		return l.LookupOrCreate(name, version, syms)
-	}
-	return load(arch, lookup, syms.IncVersion(), input, pkg, length, pn)
-}
-
-// LoadOld uses the old version of object loading.
-func LoadOld(arch *sys.Arch, syms *sym.Symbols, input *bio.Reader, pkg string, length int64, pn string) (textp []*sym.Symbol, err error) {
-	return load(arch, syms.Lookup, syms.IncVersion(), input, pkg, length, pn)
-}
-
-// loads the Xcoff file pn from f.
-// Symbols are written into syms, and a slice of the text symbols is returned.
-func load(arch *sys.Arch, lookup func(string, int) *sym.Symbol, localSymVersion int, input *bio.Reader, pkg string, length int64, pn string) (textp []*sym.Symbol, err error) {
-	errorf := func(str string, args ...interface{}) ([]*sym.Symbol, error) {
-		return nil, fmt.Errorf("loadxcoff: %v: %v", pn, fmt.Sprintf(str, args...))
-	}
-
-	var ldSections []*ldSection
-
-	f, err := xcoff.NewFile((*xcoffBiobuf)(input))
-	if err != nil {
-		return nil, err
-	}
-	defer f.Close()
-
-	for _, sect := range f.Sections {
-		//only text, data and bss section
-		if sect.Type < xcoff.STYP_TEXT || sect.Type > xcoff.STYP_BSS {
-			continue
-		}
-		lds := new(ldSection)
-		lds.Section = *sect
-		name := fmt.Sprintf("%s(%s)", pkg, lds.Name)
-		s := lookup(name, localSymVersion)
-
-		switch lds.Type {
-		default:
-			return errorf("unrecognized section type 0x%x", lds.Type)
-		case xcoff.STYP_TEXT:
-			s.Type = sym.STEXT
-		case xcoff.STYP_DATA:
-			s.Type = sym.SNOPTRDATA
-		case xcoff.STYP_BSS:
-			s.Type = sym.SNOPTRBSS
-		}
-
-		s.Size = int64(lds.Size)
-		if s.Type != sym.SNOPTRBSS {
-			data, err := lds.Section.Data()
-			if err != nil {
-				return nil, err
-			}
-			s.P = data
-		}
-
-		lds.sym = s
-		ldSections = append(ldSections, lds)
-	}
-
-	// sx = symbol from file
-	// s = symbol for syms
-	for _, sx := range f.Symbols {
-		// get symbol type
-		stype, errmsg := getSymbolType(f, sx)
-		if errmsg != "" {
-			return errorf("error reading symbol %s: %s", sx.Name, errmsg)
-		}
-		if stype == sym.Sxxx {
-			continue
-		}
-
-		s := lookup(sx.Name, 0)
-
-		// Text symbol
-		if s.Type == sym.STEXT {
-			if s.Attr.OnList() {
-				return errorf("symbol %s listed multiple times", s.Name)
-			}
-			s.Attr |= sym.AttrOnList
-			textp = append(textp, s)
-		}
-	}
-
-	// Read relocations
-	for _, sect := range ldSections {
-		// TODO(aix): Dwarf section relocation if needed
-		if sect.Type != xcoff.STYP_TEXT && sect.Type != xcoff.STYP_DATA {
-			continue
-		}
-		rs := make([]sym.Reloc, sect.Nreloc)
-		for i, rx := range sect.Relocs {
-			r := &rs[i]
-
-			r.Sym = lookup(rx.Symbol.Name, 0)
-			if uint64(int32(rx.VirtualAddress)) != rx.VirtualAddress {
-				return errorf("virtual address of a relocation is too big: 0x%x", rx.VirtualAddress)
-			}
-			r.Off = int32(rx.VirtualAddress)
-			switch rx.Type {
-			default:
-				return errorf("section %s: unknown relocation of type 0x%x", sect.Name, rx.Type)
-			case xcoff.R_POS:
-				// Reloc the address of r.Sym
-				// Length should be 64
-				if rx.Length != 64 {
-					return errorf("section %s: relocation R_POS has length different from 64: %d", sect.Name, rx.Length)
-				}
-				r.Siz = 8
-				r.Type = objabi.R_CONST
-				r.Add = int64(rx.Symbol.Value)
-
-			case xcoff.R_RBR:
-				r.Siz = 4
-				r.Type = objabi.R_CALLPOWER
-				r.Add = 0 //
-
-			}
-		}
-		s := sect.sym
-		s.R = rs
-		s.R = s.R[:sect.Nreloc]
-	}
-	return textp, nil
-
-}
-
-// Convert symbol xcoff type to sym.SymKind
-// Returns nil if this shouldn't be added into syms (like .file or .dw symbols )
-func getSymbolType(f *xcoff.File, s *xcoff.Symbol) (stype sym.SymKind, err string) {
-	// .file symbol
-	if s.SectionNumber == -2 {
-		if s.StorageClass == xcoff.C_FILE {
-			return sym.Sxxx, ""
-		}
-		return sym.Sxxx, "unrecognised StorageClass for sectionNumber = -2"
-	}
-
-	// extern symbols
-	// TODO(aix)
-	if s.SectionNumber == 0 {
-		return sym.Sxxx, ""
-	}
-
-	sectType := f.Sections[s.SectionNumber-1].SectionHeader.Type
-	switch sectType {
-	default:
-		return sym.Sxxx, fmt.Sprintf("getSymbolType for Section type 0x%x not implemented", sectType)
-	case xcoff.STYP_DWARF, xcoff.STYP_DEBUG:
-		return sym.Sxxx, ""
-	case xcoff.STYP_DATA, xcoff.STYP_BSS, xcoff.STYP_TEXT:
-	}
-
-	switch s.StorageClass {
-	default:
-		return sym.Sxxx, fmt.Sprintf("getSymbolType for Storage class 0x%x not implemented", s.StorageClass)
-	case xcoff.C_HIDEXT, xcoff.C_EXT, xcoff.C_WEAKEXT:
-		switch s.AuxCSect.StorageMappingClass {
-		default:
-			return sym.Sxxx, fmt.Sprintf("getSymbolType for Storage class 0x%x and Storage Map 0x%x not implemented", s.StorageClass, s.AuxCSect.StorageMappingClass)
-
-		// Program Code
-		case xcoff.XMC_PR:
-			if sectType == xcoff.STYP_TEXT {
-				return sym.STEXT, ""
-			}
-			return sym.Sxxx, fmt.Sprintf("unrecognised Section Type 0x%x for Storage Class 0x%x with Storage Map XMC_PR", sectType, s.StorageClass)
-
-		// Read/Write Data
-		case xcoff.XMC_RW:
-			if sectType == xcoff.STYP_DATA {
-				return sym.SDATA, ""
-			}
-			if sectType == xcoff.STYP_BSS {
-				return sym.SBSS, ""
-			}
-			return sym.Sxxx, fmt.Sprintf("unrecognised Section Type 0x%x for Storage Class 0x%x with Storage Map XMC_RW", sectType, s.StorageClass)
-
-		// Function descriptor
-		case xcoff.XMC_DS:
-			if sectType == xcoff.STYP_DATA {
-				return sym.SDATA, ""
-			}
-			return sym.Sxxx, fmt.Sprintf("unrecognised Section Type 0x%x for Storage Class 0x%x with Storage Map XMC_DS", sectType, s.StorageClass)
-
-		// TOC anchor and TOC entry
-		case xcoff.XMC_TC0, xcoff.XMC_TE:
-			if sectType == xcoff.STYP_DATA {
-				return sym.SXCOFFTOC, ""
-			}
-			return sym.Sxxx, fmt.Sprintf("unrecognised Section Type 0x%x for Storage Class 0x%x with Storage Map XMC_DS", sectType, s.StorageClass)
-
-		}
-	}
-}
diff --git a/src/cmd/oldlink/internal/mips/asm.go b/src/cmd/oldlink/internal/mips/asm.go
deleted file mode 100644
index 371c1ea..0000000
--- a/src/cmd/oldlink/internal/mips/asm.go
+++ /dev/null
@@ -1,230 +0,0 @@
-// Inferno utils/5l/asm.c
-// https://bitbucket.org/inferno-os/inferno-os/src/master/utils/5l/asm.c
-//
-//	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 © 2016 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 mips
-
-import (
-	"cmd/internal/objabi"
-	"cmd/internal/sys"
-	"cmd/oldlink/internal/ld"
-	"cmd/oldlink/internal/sym"
-	"debug/elf"
-	"fmt"
-	"log"
-)
-
-func gentext(ctxt *ld.Link) {
-	return
-}
-
-func adddynrel(ctxt *ld.Link, s *sym.Symbol, r *sym.Reloc) bool {
-	log.Fatalf("adddynrel not implemented")
-	return false
-}
-
-func elfreloc1(ctxt *ld.Link, r *sym.Reloc, sectoff int64) bool {
-	ctxt.Out.Write32(uint32(sectoff))
-
-	elfsym := r.Xsym.ElfsymForReloc()
-	switch r.Type {
-	default:
-		return false
-	case objabi.R_ADDR:
-		if r.Siz != 4 {
-			return false
-		}
-		ctxt.Out.Write32(uint32(elf.R_MIPS_32) | uint32(elfsym)<<8)
-	case objabi.R_ADDRMIPS:
-		ctxt.Out.Write32(uint32(elf.R_MIPS_LO16) | uint32(elfsym)<<8)
-	case objabi.R_ADDRMIPSU:
-		ctxt.Out.Write32(uint32(elf.R_MIPS_HI16) | uint32(elfsym)<<8)
-	case objabi.R_ADDRMIPSTLS:
-		ctxt.Out.Write32(uint32(elf.R_MIPS_TLS_TPREL_LO16) | uint32(elfsym)<<8)
-	case objabi.R_CALLMIPS, objabi.R_JMPMIPS:
-		ctxt.Out.Write32(uint32(elf.R_MIPS_26) | uint32(elfsym)<<8)
-	}
-
-	return true
-}
-
-func elfsetupplt(ctxt *ld.Link) {
-	return
-}
-
-func machoreloc1(arch *sys.Arch, out *ld.OutBuf, s *sym.Symbol, r *sym.Reloc, sectoff int64) bool {
-	return false
-}
-
-func applyrel(arch *sys.Arch, r *sym.Reloc, s *sym.Symbol, val int64, t int64) int64 {
-	o := arch.ByteOrder.Uint32(s.P[r.Off:])
-	switch r.Type {
-	case objabi.R_ADDRMIPS, objabi.R_ADDRMIPSTLS:
-		return int64(o&0xffff0000 | uint32(t)&0xffff)
-	case objabi.R_ADDRMIPSU:
-		return int64(o&0xffff0000 | uint32((t+(1<<15))>>16)&0xffff)
-	case objabi.R_CALLMIPS, objabi.R_JMPMIPS:
-		return int64(o&0xfc000000 | uint32(t>>2)&^0xfc000000)
-	default:
-		return val
-	}
-}
-
-func archreloc(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, val int64) (int64, bool) {
-	if ctxt.LinkMode == ld.LinkExternal {
-		switch r.Type {
-		default:
-			return val, false
-		case objabi.R_ADDRMIPS, objabi.R_ADDRMIPSU:
-			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 += ld.Symaddr(rs) - ld.Symaddr(rs.Outer)
-				rs = rs.Outer
-			}
-
-			if rs.Type != sym.SHOSTOBJ && rs.Type != sym.SDYNIMPORT && rs.Sect == nil {
-				ld.Errorf(s, "missing section for %s", rs.Name)
-			}
-			r.Xsym = rs
-			return applyrel(ctxt.Arch, r, s, val, r.Xadd), true
-		case objabi.R_ADDRMIPSTLS, objabi.R_CALLMIPS, objabi.R_JMPMIPS:
-			r.Done = false
-			r.Xsym = r.Sym
-			r.Xadd = r.Add
-			return applyrel(ctxt.Arch, r, s, val, r.Add), true
-		}
-	}
-
-	switch r.Type {
-	case objabi.R_CONST:
-		return r.Add, true
-	case objabi.R_GOTOFF:
-		return ld.Symaddr(r.Sym) + r.Add - ld.Symaddr(ctxt.Syms.Lookup(".got", 0)), true
-	case objabi.R_ADDRMIPS, objabi.R_ADDRMIPSU:
-		t := ld.Symaddr(r.Sym) + r.Add
-		return applyrel(ctxt.Arch, r, s, val, t), true
-	case objabi.R_CALLMIPS, objabi.R_JMPMIPS:
-		t := ld.Symaddr(r.Sym) + r.Add
-
-		if t&3 != 0 {
-			ld.Errorf(s, "direct call is not aligned: %s %x", r.Sym.Name, t)
-		}
-
-		// check if target address is in the same 256 MB region as the next instruction
-		if (s.Value+int64(r.Off)+4)&0xf0000000 != (t & 0xf0000000) {
-			ld.Errorf(s, "direct call too far: %s %x", r.Sym.Name, t)
-		}
-
-		return applyrel(ctxt.Arch, r, s, val, t), true
-	case objabi.R_ADDRMIPSTLS:
-		// thread pointer is at 0x7000 offset from the start of TLS data area
-		t := ld.Symaddr(r.Sym) + r.Add - 0x7000
-		if t < -32768 || t >= 32678 {
-			ld.Errorf(s, "TLS offset out of range %d", t)
-		}
-		return applyrel(ctxt.Arch, r, s, val, t), true
-	}
-
-	return val, false
-}
-
-func archrelocvariant(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, t int64) int64 {
-	return -1
-}
-
-func asmb(ctxt *ld.Link) {
-	if ctxt.IsELF {
-		ld.Asmbelfsetup()
-	}
-
-	sect := ld.Segtext.Sections[0]
-	ctxt.Out.SeekSet(int64(sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff))
-	ld.Codeblk(ctxt, int64(sect.Vaddr), int64(sect.Length))
-	for _, sect = range ld.Segtext.Sections[1:] {
-		ctxt.Out.SeekSet(int64(sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff))
-		ld.Datblk(ctxt, int64(sect.Vaddr), int64(sect.Length))
-	}
-
-	if ld.Segrodata.Filelen > 0 {
-		ctxt.Out.SeekSet(int64(ld.Segrodata.Fileoff))
-		ld.Datblk(ctxt, int64(ld.Segrodata.Vaddr), int64(ld.Segrodata.Filelen))
-	}
-
-	ctxt.Out.SeekSet(int64(ld.Segdata.Fileoff))
-	ld.Datblk(ctxt, int64(ld.Segdata.Vaddr), int64(ld.Segdata.Filelen))
-
-	ctxt.Out.SeekSet(int64(ld.Segdwarf.Fileoff))
-	ld.Dwarfblk(ctxt, int64(ld.Segdwarf.Vaddr), int64(ld.Segdwarf.Filelen))
-}
-
-func asmb2(ctxt *ld.Link) {
-	/* output symbol table */
-	ld.Symsize = 0
-
-	ld.Lcsize = 0
-	symo := uint32(0)
-	if !*ld.FlagS {
-		if !ctxt.IsELF {
-			ld.Errorf(nil, "unsupported executable format")
-		}
-		symo = uint32(ld.Segdwarf.Fileoff + ld.Segdwarf.Filelen)
-		symo = uint32(ld.Rnd(int64(symo), int64(*ld.FlagRound)))
-
-		ctxt.Out.SeekSet(int64(symo))
-		ld.Asmelfsym(ctxt)
-		ctxt.Out.Flush()
-		ctxt.Out.Write(ld.Elfstrdat)
-
-		if ctxt.LinkMode == ld.LinkExternal {
-			ld.Elfemitreloc(ctxt)
-		}
-	}
-
-	ctxt.Out.SeekSet(0)
-	switch ctxt.HeadType {
-	default:
-		ld.Errorf(nil, "unsupported operating system")
-	case objabi.Hlinux:
-		ld.Asmbelf(ctxt, int64(symo))
-	}
-
-	ctxt.Out.Flush()
-	if *ld.FlagC {
-		fmt.Printf("textsize=%d\n", ld.Segtext.Filelen)
-		fmt.Printf("datsize=%d\n", ld.Segdata.Filelen)
-		fmt.Printf("bsssize=%d\n", ld.Segdata.Length-ld.Segdata.Filelen)
-		fmt.Printf("symsize=%d\n", ld.Symsize)
-		fmt.Printf("lcsize=%d\n", ld.Lcsize)
-		fmt.Printf("total=%d\n", ld.Segtext.Filelen+ld.Segdata.Length+uint64(ld.Symsize)+uint64(ld.Lcsize))
-	}
-}
diff --git a/src/cmd/oldlink/internal/mips/l.go b/src/cmd/oldlink/internal/mips/l.go
deleted file mode 100644
index affc48c..0000000
--- a/src/cmd/oldlink/internal/mips/l.go
+++ /dev/null
@@ -1,74 +0,0 @@
-// Inferno utils/5l/asm.c
-// https://bitbucket.org/inferno-os/inferno-os/src/master/utils/5l/asm.c
-//
-//	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 © 2016 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 mips
-
-// Writing object files.
-
-// cmd/9l/l.h from Vita Nuova.
-//
-//	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-2008 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-2008 Lucent Technologies Inc. and others
-//	Portions Copyright © 2016 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.
-
-const (
-	MaxAlign  = 32 // max data alignment
-	MinAlign  = 1  // min data alignment
-	FuncAlign = 4
-)
-
-/* Used by ../internal/ld/dwarf.go */
-const (
-	DWARFREGSP = 29
-	DWARFREGLR = 31
-)
diff --git a/src/cmd/oldlink/internal/mips/obj.go b/src/cmd/oldlink/internal/mips/obj.go
deleted file mode 100644
index a59bc21..0000000
--- a/src/cmd/oldlink/internal/mips/obj.go
+++ /dev/null
@@ -1,89 +0,0 @@
-// Inferno utils/5l/obj.c
-// https://bitbucket.org/inferno-os/inferno-os/src/master/utils/5l/obj.c
-//
-//	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 © 2016 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 mips
-
-import (
-	"cmd/internal/objabi"
-	"cmd/internal/sys"
-	"cmd/oldlink/internal/ld"
-)
-
-func Init() (*sys.Arch, ld.Arch) {
-	arch := sys.ArchMIPS
-	if objabi.GOARCH == "mipsle" {
-		arch = sys.ArchMIPSLE
-	}
-
-	theArch := ld.Arch{
-		Funcalign:  FuncAlign,
-		Maxalign:   MaxAlign,
-		Minalign:   MinAlign,
-		Dwarfregsp: DWARFREGSP,
-		Dwarfreglr: DWARFREGLR,
-
-		Adddynrel:        adddynrel,
-		Archinit:         archinit,
-		Archreloc:        archreloc,
-		Archrelocvariant: archrelocvariant,
-		Asmb:             asmb,
-		Asmb2:            asmb2,
-		Elfreloc1:        elfreloc1,
-		Elfsetupplt:      elfsetupplt,
-		Gentext:          gentext,
-		Machoreloc1:      machoreloc1,
-
-		Linuxdynld: "/lib/ld.so.1",
-
-		Freebsddynld:   "XXX",
-		Openbsddynld:   "XXX",
-		Netbsddynld:    "XXX",
-		Dragonflydynld: "XXX",
-		Solarisdynld:   "XXX",
-	}
-
-	return arch, theArch
-}
-
-func archinit(ctxt *ld.Link) {
-	switch ctxt.HeadType {
-	default:
-		ld.Exitf("unknown -H option: %v", ctxt.HeadType)
-	case objabi.Hlinux: /* mips elf */
-		ld.Elfinit(ctxt)
-		ld.HEADR = ld.ELFRESERVE
-		if *ld.FlagTextAddr == -1 {
-			*ld.FlagTextAddr = 0x10000 + int64(ld.HEADR)
-		}
-		if *ld.FlagRound == -1 {
-			*ld.FlagRound = 0x10000
-		}
-	}
-}
diff --git a/src/cmd/oldlink/internal/mips64/asm.go b/src/cmd/oldlink/internal/mips64/asm.go
deleted file mode 100644
index 7dcf805..0000000
--- a/src/cmd/oldlink/internal/mips64/asm.go
+++ /dev/null
@@ -1,278 +0,0 @@
-// Inferno utils/5l/asm.c
-// https://bitbucket.org/inferno-os/inferno-os/src/master/utils/5l/asm.c
-//
-//	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 mips64
-
-import (
-	"cmd/internal/objabi"
-	"cmd/internal/sys"
-	"cmd/oldlink/internal/ld"
-	"cmd/oldlink/internal/sym"
-	"debug/elf"
-	"fmt"
-	"log"
-)
-
-func gentext(ctxt *ld.Link) {}
-
-func adddynrel(ctxt *ld.Link, s *sym.Symbol, r *sym.Reloc) bool {
-	log.Fatalf("adddynrel not implemented")
-	return false
-}
-
-func elfreloc1(ctxt *ld.Link, r *sym.Reloc, sectoff int64) bool {
-	// mips64 ELF relocation (endian neutral)
-	//		offset	uint64
-	//		sym		uint32
-	//		ssym	uint8
-	//		type3	uint8
-	//		type2	uint8
-	//		type	uint8
-	//		addend	int64
-
-	ctxt.Out.Write64(uint64(sectoff))
-
-	elfsym := r.Xsym.ElfsymForReloc()
-	ctxt.Out.Write32(uint32(elfsym))
-	ctxt.Out.Write8(0)
-	ctxt.Out.Write8(0)
-	ctxt.Out.Write8(0)
-	switch r.Type {
-	default:
-		return false
-	case objabi.R_ADDR:
-		switch r.Siz {
-		case 4:
-			ctxt.Out.Write8(uint8(elf.R_MIPS_32))
-		case 8:
-			ctxt.Out.Write8(uint8(elf.R_MIPS_64))
-		default:
-			return false
-		}
-	case objabi.R_ADDRMIPS:
-		ctxt.Out.Write8(uint8(elf.R_MIPS_LO16))
-	case objabi.R_ADDRMIPSU:
-		ctxt.Out.Write8(uint8(elf.R_MIPS_HI16))
-	case objabi.R_ADDRMIPSTLS:
-		ctxt.Out.Write8(uint8(elf.R_MIPS_TLS_TPREL_LO16))
-	case objabi.R_CALLMIPS,
-		objabi.R_JMPMIPS:
-		ctxt.Out.Write8(uint8(elf.R_MIPS_26))
-	}
-	ctxt.Out.Write64(uint64(r.Xadd))
-
-	return true
-}
-
-func elfsetupplt(ctxt *ld.Link) {
-	return
-}
-
-func machoreloc1(arch *sys.Arch, out *ld.OutBuf, s *sym.Symbol, r *sym.Reloc, sectoff int64) bool {
-	return false
-}
-
-func archreloc(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, val int64) (int64, bool) {
-	if ctxt.LinkMode == ld.LinkExternal {
-		switch r.Type {
-		default:
-			return val, false
-		case objabi.R_ADDRMIPS,
-			objabi.R_ADDRMIPSU:
-			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 += ld.Symaddr(rs) - ld.Symaddr(rs.Outer)
-				rs = rs.Outer
-			}
-
-			if rs.Type != sym.SHOSTOBJ && rs.Type != sym.SDYNIMPORT && rs.Sect == nil {
-				ld.Errorf(s, "missing section for %s", rs.Name)
-			}
-			r.Xsym = rs
-
-			return val, true
-		case objabi.R_ADDRMIPSTLS,
-			objabi.R_CALLMIPS,
-			objabi.R_JMPMIPS:
-			r.Done = false
-			r.Xsym = r.Sym
-			r.Xadd = r.Add
-			return val, true
-		}
-	}
-
-	switch r.Type {
-	case objabi.R_CONST:
-		return r.Add, true
-	case objabi.R_GOTOFF:
-		return ld.Symaddr(r.Sym) + r.Add - ld.Symaddr(ctxt.Syms.Lookup(".got", 0)), true
-	case objabi.R_ADDRMIPS,
-		objabi.R_ADDRMIPSU:
-		t := ld.Symaddr(r.Sym) + r.Add
-		o1 := ctxt.Arch.ByteOrder.Uint32(s.P[r.Off:])
-		if r.Type == objabi.R_ADDRMIPS {
-			return int64(o1&0xffff0000 | uint32(t)&0xffff), true
-		}
-		return int64(o1&0xffff0000 | uint32((t+1<<15)>>16)&0xffff), true
-	case objabi.R_ADDRMIPSTLS:
-		// thread pointer is at 0x7000 offset from the start of TLS data area
-		t := ld.Symaddr(r.Sym) + r.Add - 0x7000
-		if t < -32768 || t >= 32678 {
-			ld.Errorf(s, "TLS offset out of range %d", t)
-		}
-		o1 := ctxt.Arch.ByteOrder.Uint32(s.P[r.Off:])
-		return int64(o1&0xffff0000 | uint32(t)&0xffff), true
-	case objabi.R_CALLMIPS,
-		objabi.R_JMPMIPS:
-		// Low 26 bits = (S + A) >> 2
-		t := ld.Symaddr(r.Sym) + r.Add
-		o1 := ctxt.Arch.ByteOrder.Uint32(s.P[r.Off:])
-		return int64(o1&0xfc000000 | uint32(t>>2)&^0xfc000000), true
-	}
-
-	return val, false
-}
-
-func archrelocvariant(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, t int64) int64 {
-	return -1
-}
-
-func asmb(ctxt *ld.Link) {
-	if ctxt.IsELF {
-		ld.Asmbelfsetup()
-	}
-
-	sect := ld.Segtext.Sections[0]
-	ctxt.Out.SeekSet(int64(sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff))
-	ld.Codeblk(ctxt, int64(sect.Vaddr), int64(sect.Length))
-	for _, sect = range ld.Segtext.Sections[1:] {
-		ctxt.Out.SeekSet(int64(sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff))
-		ld.Datblk(ctxt, int64(sect.Vaddr), int64(sect.Length))
-	}
-
-	if ld.Segrodata.Filelen > 0 {
-		ctxt.Out.SeekSet(int64(ld.Segrodata.Fileoff))
-		ld.Datblk(ctxt, int64(ld.Segrodata.Vaddr), int64(ld.Segrodata.Filelen))
-	}
-	if ld.Segrelrodata.Filelen > 0 {
-		ctxt.Out.SeekSet(int64(ld.Segrelrodata.Fileoff))
-		ld.Datblk(ctxt, int64(ld.Segrelrodata.Vaddr), int64(ld.Segrelrodata.Filelen))
-	}
-
-	ctxt.Out.SeekSet(int64(ld.Segdata.Fileoff))
-	ld.Datblk(ctxt, int64(ld.Segdata.Vaddr), int64(ld.Segdata.Filelen))
-
-	ctxt.Out.SeekSet(int64(ld.Segdwarf.Fileoff))
-	ld.Dwarfblk(ctxt, int64(ld.Segdwarf.Vaddr), int64(ld.Segdwarf.Filelen))
-}
-
-func asmb2(ctxt *ld.Link) {
-	/* output symbol table */
-	ld.Symsize = 0
-
-	ld.Lcsize = 0
-	symo := uint32(0)
-	if !*ld.FlagS {
-		// TODO: rationalize
-		switch ctxt.HeadType {
-		default:
-			if ctxt.IsELF {
-				symo = uint32(ld.Segdwarf.Fileoff + ld.Segdwarf.Filelen)
-				symo = uint32(ld.Rnd(int64(symo), int64(*ld.FlagRound)))
-			}
-
-		case objabi.Hplan9:
-			symo = uint32(ld.Segdata.Fileoff + ld.Segdata.Filelen)
-		}
-
-		ctxt.Out.SeekSet(int64(symo))
-		switch ctxt.HeadType {
-		default:
-			if ctxt.IsELF {
-				ld.Asmelfsym(ctxt)
-				ctxt.Out.Flush()
-				ctxt.Out.Write(ld.Elfstrdat)
-
-				if ctxt.LinkMode == ld.LinkExternal {
-					ld.Elfemitreloc(ctxt)
-				}
-			}
-
-		case objabi.Hplan9:
-			ld.Asmplan9sym(ctxt)
-			ctxt.Out.Flush()
-
-			sym := ctxt.Syms.Lookup("pclntab", 0)
-			if sym != nil {
-				ld.Lcsize = int32(len(sym.P))
-				ctxt.Out.Write(sym.P)
-				ctxt.Out.Flush()
-			}
-		}
-	}
-
-	ctxt.Out.SeekSet(0)
-	switch ctxt.HeadType {
-	default:
-	case objabi.Hplan9: /* plan 9 */
-		magic := uint32(4*18*18 + 7)
-		if ctxt.Arch == sys.ArchMIPS64LE {
-			magic = uint32(4*26*26 + 7)
-		}
-		ctxt.Out.Write32(magic)                      /* magic */
-		ctxt.Out.Write32(uint32(ld.Segtext.Filelen)) /* sizes */
-		ctxt.Out.Write32(uint32(ld.Segdata.Filelen))
-		ctxt.Out.Write32(uint32(ld.Segdata.Length - ld.Segdata.Filelen))
-		ctxt.Out.Write32(uint32(ld.Symsize))          /* nsyms */
-		ctxt.Out.Write32(uint32(ld.Entryvalue(ctxt))) /* va of entry */
-		ctxt.Out.Write32(0)
-		ctxt.Out.Write32(uint32(ld.Lcsize))
-
-	case objabi.Hlinux,
-		objabi.Hfreebsd,
-		objabi.Hnetbsd,
-		objabi.Hopenbsd:
-		ld.Asmbelf(ctxt, int64(symo))
-	}
-
-	ctxt.Out.Flush()
-	if *ld.FlagC {
-		fmt.Printf("textsize=%d\n", ld.Segtext.Filelen)
-		fmt.Printf("datsize=%d\n", ld.Segdata.Filelen)
-		fmt.Printf("bsssize=%d\n", ld.Segdata.Length-ld.Segdata.Filelen)
-		fmt.Printf("symsize=%d\n", ld.Symsize)
-		fmt.Printf("lcsize=%d\n", ld.Lcsize)
-		fmt.Printf("total=%d\n", ld.Segtext.Filelen+ld.Segdata.Length+uint64(ld.Symsize)+uint64(ld.Lcsize))
-	}
-}
diff --git a/src/cmd/oldlink/internal/mips64/l.go b/src/cmd/oldlink/internal/mips64/l.go
deleted file mode 100644
index 837af0e..0000000
--- a/src/cmd/oldlink/internal/mips64/l.go
+++ /dev/null
@@ -1,74 +0,0 @@
-// Inferno utils/5l/asm.c
-// https://bitbucket.org/inferno-os/inferno-os/src/master/utils/5l/asm.c
-//
-//	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 mips64
-
-// Writing object files.
-
-// cmd/9l/l.h from Vita Nuova.
-//
-//	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-2008 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-2008 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.
-
-const (
-	maxAlign  = 32 // max data alignment
-	minAlign  = 1  // min data alignment
-	funcAlign = 8
-)
-
-/* Used by ../internal/ld/dwarf.go */
-const (
-	dwarfRegSP = 29
-	dwarfRegLR = 31
-)
diff --git a/src/cmd/oldlink/internal/mips64/obj.go b/src/cmd/oldlink/internal/mips64/obj.go
deleted file mode 100644
index 25a5153..0000000
--- a/src/cmd/oldlink/internal/mips64/obj.go
+++ /dev/null
@@ -1,98 +0,0 @@
-// Inferno utils/5l/obj.c
-// https://bitbucket.org/inferno-os/inferno-os/src/master/utils/5l/obj.c
-//
-//	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 mips64
-
-import (
-	"cmd/internal/objabi"
-	"cmd/internal/sys"
-	"cmd/oldlink/internal/ld"
-)
-
-func Init() (*sys.Arch, ld.Arch) {
-	arch := sys.ArchMIPS64
-	if objabi.GOARCH == "mips64le" {
-		arch = sys.ArchMIPS64LE
-	}
-
-	theArch := ld.Arch{
-		Funcalign:        funcAlign,
-		Maxalign:         maxAlign,
-		Minalign:         minAlign,
-		Dwarfregsp:       dwarfRegSP,
-		Dwarfreglr:       dwarfRegLR,
-		Adddynrel:        adddynrel,
-		Archinit:         archinit,
-		Archreloc:        archreloc,
-		Archrelocvariant: archrelocvariant,
-		Asmb:             asmb,
-		Asmb2:            asmb2,
-		Elfreloc1:        elfreloc1,
-		Elfsetupplt:      elfsetupplt,
-		Gentext:          gentext,
-		Machoreloc1:      machoreloc1,
-
-		Linuxdynld:     "/lib64/ld64.so.1",
-		Freebsddynld:   "XXX",
-		Openbsddynld:   "XXX",
-		Netbsddynld:    "XXX",
-		Dragonflydynld: "XXX",
-		Solarisdynld:   "XXX",
-	}
-
-	return arch, theArch
-}
-
-func archinit(ctxt *ld.Link) {
-	switch ctxt.HeadType {
-	default:
-		ld.Exitf("unknown -H option: %v", ctxt.HeadType)
-
-	case objabi.Hplan9: /* plan 9 */
-		ld.HEADR = 32
-
-		if *ld.FlagTextAddr == -1 {
-			*ld.FlagTextAddr = 16*1024 + int64(ld.HEADR)
-		}
-		if *ld.FlagRound == -1 {
-			*ld.FlagRound = 16 * 1024
-		}
-
-	case objabi.Hlinux: /* mips64 elf */
-		ld.Elfinit(ctxt)
-		ld.HEADR = ld.ELFRESERVE
-		if *ld.FlagTextAddr == -1 {
-			*ld.FlagTextAddr = 0x10000 + int64(ld.HEADR)
-		}
-		if *ld.FlagRound == -1 {
-			*ld.FlagRound = 0x10000
-		}
-	}
-}
diff --git a/src/cmd/oldlink/internal/objfile/objfile.go b/src/cmd/oldlink/internal/objfile/objfile.go
deleted file mode 100644
index fbd7eb7..0000000
--- a/src/cmd/oldlink/internal/objfile/objfile.go
+++ /dev/null
@@ -1,664 +0,0 @@
-// Copyright 2013 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 objfile reads Go object files for the Go linker, cmd/link.
-//
-// This package is similar to cmd/internal/objfile which also reads
-// Go object files.
-package objfile
-
-import (
-	"bufio"
-	"bytes"
-	"cmd/internal/bio"
-	"cmd/internal/dwarf"
-	"cmd/internal/goobj2"
-	"cmd/internal/obj"
-	"cmd/internal/objabi"
-	"cmd/internal/sys"
-	"cmd/oldlink/internal/sym"
-	"fmt"
-	"internal/unsafeheader"
-	"io"
-	"log"
-	"os"
-	"strconv"
-	"strings"
-	"unsafe"
-)
-
-const (
-	startmagic = "\x00go114ld"
-	endmagic   = "\xffgo114ld"
-)
-
-var emptyPkg = []byte(`"".`)
-
-// objReader reads Go object files.
-type objReader struct {
-	rd              *bio.Reader
-	arch            *sys.Arch
-	syms            *sym.Symbols
-	lib             *sym.Library
-	unit            *sym.CompilationUnit
-	pn              string
-	dupSym          *sym.Symbol
-	localSymVersion int
-	flags           int
-	strictDupMsgs   int
-	dataSize        int
-
-	// rdBuf is used by readString and readSymName as scratch for reading strings.
-	rdBuf []byte
-
-	// List of symbol references for the file being read.
-	refs        []*sym.Symbol
-	data        []byte
-	reloc       []sym.Reloc
-	pcdata      []sym.Pcdata
-	funcdata    []*sym.Symbol
-	funcdataoff []int64
-	file        []*sym.Symbol
-	pkgpref     string // objabi.PathToPrefix(r.lib.Pkg) + "."
-
-	roObject []byte // from read-only mmap of object file (may be nil)
-	roOffset int64  // offset into readonly object data examined so far
-
-	dataReadOnly bool // whether data is backed by read-only memory
-}
-
-// Flags to enable optional behavior during object loading/reading.
-
-const (
-	NoFlag int = iota
-
-	// Sanity-check duplicate symbol contents, issuing warning
-	// when duplicates have different lengths or contents.
-	StrictDupsWarnFlag
-
-	// Similar to StrictDupsWarnFlag, but issue fatal error.
-	StrictDupsErrFlag
-)
-
-// Load loads an object file f into library lib.
-// The symbols loaded are added to syms.
-func Load(arch *sys.Arch, syms *sym.Symbols, f *bio.Reader, lib *sym.Library, unit *sym.CompilationUnit, length int64, pn string, flags int) int {
-	start := f.Offset()
-	roObject := f.SliceRO(uint64(length))
-	if roObject != nil {
-		f.MustSeek(int64(-length), os.SEEK_CUR)
-	}
-	r := &objReader{
-		rd:              f,
-		lib:             lib,
-		unit:            unit,
-		arch:            arch,
-		syms:            syms,
-		pn:              pn,
-		dupSym:          &sym.Symbol{Name: ".dup"},
-		localSymVersion: syms.IncVersion(),
-		flags:           flags,
-		roObject:        roObject,
-		pkgpref:         objabi.PathToPrefix(lib.Pkg) + ".",
-	}
-	r.loadObjFile()
-	if roObject != nil {
-		if r.roOffset != length {
-			log.Fatalf("%s: unexpected end at %d, want %d", pn, r.roOffset, start+length)
-		}
-		r.rd.MustSeek(int64(length), os.SEEK_CUR)
-	} else if f.Offset() != start+length {
-		log.Fatalf("%s: unexpected end at %d, want %d", pn, f.Offset(), start+length)
-	}
-	return r.strictDupMsgs
-}
-
-func (r *objReader) loadObjFile() {
-	// Magic header
-	var buf [8]uint8
-	r.readFull(buf[:])
-	if string(buf[:]) != startmagic {
-		if string(buf[:]) == goobj2.Magic {
-			log.Fatalf("found object file %s in new format, but -go115newobj is false\nset -go115newobj consistently in all -gcflags, -asmflags, and -ldflags", r.pn)
-		}
-		log.Fatalf("%s: invalid file start %x %x %x %x %x %x %x %x", r.pn, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7])
-	}
-
-	// Version
-	c, err := r.readByte()
-	if err != nil || c != 1 {
-		log.Fatalf("%s: invalid file version number %d", r.pn, c)
-	}
-
-	// Autolib
-	for {
-		lib := r.readString()
-		if lib == "" {
-			break
-		}
-		r.lib.ImportStrings = append(r.lib.ImportStrings, lib)
-	}
-
-	// DWARF strings
-	count := r.readInt()
-	r.unit.DWARFFileTable = make([]string, count)
-	for i := 0; i < count; i++ {
-		// TODO: This should probably be a call to mkROString.
-		r.unit.DWARFFileTable[i] = r.readString()
-	}
-
-	// Symbol references
-	r.refs = []*sym.Symbol{nil} // zeroth ref is nil
-	for {
-		c, err := r.peek(1)
-		if err != nil {
-			log.Fatalf("%s: peeking: %v", r.pn, err)
-		}
-		if c[0] == 0xff {
-			r.readByte()
-			break
-		}
-		r.readRef()
-	}
-
-	// Lengths
-	r.readSlices()
-
-	// Data section
-	err = r.readDataSection()
-	if err != nil {
-		log.Fatalf("%s: error reading %s", r.pn, err)
-	}
-
-	// Defined symbols
-	for {
-		c, err := r.peek(1)
-		if err != nil {
-			log.Fatalf("%s: peeking: %v", r.pn, err)
-		}
-		if c[0] == 0xff {
-			break
-		}
-		r.readSym()
-	}
-
-	// Magic footer
-	buf = [8]uint8{}
-	r.readFull(buf[:])
-	if string(buf[:]) != endmagic {
-		log.Fatalf("%s: invalid file end", r.pn)
-	}
-}
-
-func (r *objReader) readSlices() {
-	r.dataSize = r.readInt()
-	n := r.readInt()
-	r.reloc = make([]sym.Reloc, n)
-	n = r.readInt()
-	r.pcdata = make([]sym.Pcdata, n)
-	_ = r.readInt() // TODO: remove on next object file rev (autom count)
-	n = r.readInt()
-	r.funcdata = make([]*sym.Symbol, n)
-	r.funcdataoff = make([]int64, n)
-	n = r.readInt()
-	r.file = make([]*sym.Symbol, n)
-}
-
-func (r *objReader) readDataSection() (err error) {
-	if r.roObject != nil {
-		r.data, r.dataReadOnly, err =
-			r.roObject[r.roOffset:r.roOffset+int64(r.dataSize)], true, nil
-		r.roOffset += int64(r.dataSize)
-		return
-	}
-	r.data, r.dataReadOnly, err = r.rd.Slice(uint64(r.dataSize))
-	return
-}
-
-// Symbols are prefixed so their content doesn't get confused with the magic footer.
-const symPrefix = 0xfe
-
-func (r *objReader) readSym() {
-	var c byte
-	var err error
-	if c, err = r.readByte(); c != symPrefix || err != nil {
-		log.Fatalln("readSym out of sync")
-	}
-	if c, err = r.readByte(); err != nil {
-		log.Fatalln("error reading input: ", err)
-	}
-	t := sym.AbiSymKindToSymKind[c]
-	s := r.readSymIndex()
-	flags := r.readInt()
-	dupok := flags&1 != 0
-	local := flags&2 != 0
-	makeTypelink := flags&4 != 0
-	size := r.readInt()
-	typ := r.readSymIndex()
-	data := r.readData()
-	nreloc := r.readInt()
-	isdup := false
-
-	var dup *sym.Symbol
-	if s.Type != 0 && s.Type != sym.SXREF {
-		if (t == sym.SDATA || t == sym.SBSS || t == sym.SNOPTRBSS) && len(data) == 0 && nreloc == 0 {
-			if s.Size < int64(size) {
-				s.Size = int64(size)
-			}
-			if typ != nil && s.Gotype == nil {
-				s.Gotype = typ
-			}
-			return
-		}
-
-		if (s.Type == sym.SDATA || s.Type == sym.SBSS || s.Type == sym.SNOPTRBSS) && len(s.P) == 0 && len(s.R) == 0 {
-			goto overwrite
-		}
-		if s.Type != sym.SBSS && s.Type != sym.SNOPTRBSS && !dupok && !s.Attr.DuplicateOK() {
-			log.Fatalf("duplicate symbol %s (types %d and %d) in %s and %s", s.Name, s.Type, t, s.File, r.pn)
-		}
-		if len(s.P) > 0 {
-			dup = s
-			s = r.dupSym
-			isdup = true
-		}
-	}
-
-overwrite:
-	s.File = r.pkgpref[:len(r.pkgpref)-1]
-	s.Unit = r.unit
-	if dupok {
-		s.Attr |= sym.AttrDuplicateOK
-	}
-	if t == sym.SXREF {
-		log.Fatalf("bad sxref")
-	}
-	if t == 0 {
-		log.Fatalf("missing type for %s in %s", s.Name, r.pn)
-	}
-	if t == sym.SBSS && (s.Type == sym.SRODATA || s.Type == sym.SNOPTRBSS) {
-		t = s.Type
-	}
-	s.Type = t
-	if s.Size < int64(size) {
-		s.Size = int64(size)
-	}
-	s.Attr.Set(sym.AttrLocal, local)
-	s.Attr.Set(sym.AttrMakeTypelink, makeTypelink)
-	if typ != nil {
-		s.Gotype = typ
-	}
-	if isdup && typ != nil { // if bss sym defined multiple times, take type from any one def
-		dup.Gotype = typ
-	}
-	s.P = data
-	s.Attr.Set(sym.AttrReadOnly, r.dataReadOnly)
-	if nreloc > 0 {
-		s.R = r.reloc[:nreloc:nreloc]
-		if !isdup {
-			r.reloc = r.reloc[nreloc:]
-		}
-
-		for i := 0; i < nreloc; i++ {
-			s.R[i] = sym.Reloc{
-				Off:  r.readInt32(),
-				Siz:  r.readUint8(),
-				Type: objabi.RelocType(r.readInt32()),
-				Add:  r.readInt64(),
-				Sym:  r.readSymIndex(),
-			}
-		}
-	}
-
-	if s.Type == sym.STEXT {
-		s.FuncInfo = new(sym.FuncInfo)
-		pc := s.FuncInfo
-
-		pc.Args = r.readInt32()
-		pc.Locals = r.readInt32()
-		s.Align = r.readInt32()
-		if r.readUint8() != 0 {
-			s.Attr |= sym.AttrNoSplit
-		}
-		flags := r.readInt()
-		if flags&(1<<2) != 0 {
-			s.Attr |= sym.AttrReflectMethod
-		}
-		if flags&(1<<3) != 0 {
-			s.Attr |= sym.AttrShared
-		}
-		if flags&(1<<4) != 0 {
-			s.Attr |= sym.AttrTopFrame
-		}
-		n := r.readInt()
-		if n != 0 {
-			log.Fatalf("stale object file: autom count nonzero")
-		}
-
-		pc.Pcsp.P = r.readData()
-		pc.Pcfile.P = r.readData()
-		pc.Pcline.P = r.readData()
-		pc.Pcinline.P = r.readData()
-		n = r.readInt()
-		pc.Pcdata = r.pcdata[:n:n]
-		if !isdup {
-			r.pcdata = r.pcdata[n:]
-		}
-		for i := 0; i < n; i++ {
-			pc.Pcdata[i].P = r.readData()
-		}
-		n = r.readInt()
-		pc.Funcdata = r.funcdata[:n:n]
-		pc.Funcdataoff = r.funcdataoff[:n:n]
-		if !isdup {
-			r.funcdata = r.funcdata[n:]
-			r.funcdataoff = r.funcdataoff[n:]
-		}
-		for i := 0; i < n; i++ {
-			pc.Funcdata[i] = r.readSymIndex()
-		}
-		for i := 0; i < n; i++ {
-			pc.Funcdataoff[i] = r.readInt64()
-		}
-		n = r.readInt()
-		pc.File = r.file[:n:n]
-		if !isdup {
-			r.file = r.file[n:]
-		}
-		for i := 0; i < n; i++ {
-			pc.File[i] = r.readSymIndex()
-		}
-		n = r.readInt()
-		pc.InlTree = make([]sym.InlinedCall, n)
-		for i := 0; i < n; i++ {
-			pc.InlTree[i].Parent = r.readInt32()
-			pc.InlTree[i].File = r.readSymIndex()
-			pc.InlTree[i].Line = r.readInt32()
-			pc.InlTree[i].Func = r.readSymIndex().Name
-			pc.InlTree[i].ParentPC = r.readInt32()
-		}
-
-		if !dupok {
-			if s.Attr.OnList() {
-				log.Fatalf("symbol %s listed multiple times", s.Name)
-			}
-			s.Attr |= sym.AttrOnList
-			r.lib.Textp = append(r.lib.Textp, s)
-		} else {
-			// there may ba a dup in another package
-			// put into a temp list and add to text later
-			if !isdup {
-				r.lib.DupTextSyms = append(r.lib.DupTextSyms, s)
-			} else {
-				r.lib.DupTextSyms = append(r.lib.DupTextSyms, dup)
-			}
-		}
-	}
-	if s.Type == sym.SDWARFINFO {
-		r.patchDWARFName(s)
-	}
-
-	if isdup && r.flags&(StrictDupsWarnFlag|StrictDupsErrFlag) != 0 {
-		// Compare the just-read symbol with the previously read
-		// symbol of the same name, verifying that they have the same
-		// payload. If not, issue a warning and possibly an error.
-		if !bytes.Equal(s.P, dup.P) {
-			reason := "same length but different contents"
-			if len(s.P) != len(dup.P) {
-				reason = fmt.Sprintf("new length %d != old length %d",
-					len(data), len(dup.P))
-			}
-			fmt.Fprintf(os.Stderr, "cmd/link: while reading object for '%v': duplicate symbol '%s', previous def at '%v', with mismatched payload: %s\n", r.lib, dup, dup.Unit.Lib, reason)
-
-			// For the moment, allow DWARF subprogram DIEs for
-			// auto-generated wrapper functions. What seems to happen
-			// here is that we get different line numbers on formal
-			// params; I am guessing that the pos is being inherited
-			// from the spot where the wrapper is needed.
-			allowed := (strings.HasPrefix(dup.Name, "go.info.go.interface") ||
-				strings.HasPrefix(dup.Name, "go.info.go.builtin") ||
-				strings.HasPrefix(dup.Name, "go.isstmt.go.builtin") ||
-				strings.HasPrefix(dup.Name, "go.debuglines"))
-			if !allowed {
-				r.strictDupMsgs++
-			}
-		}
-	}
-}
-
-func (r *objReader) patchDWARFName(s *sym.Symbol) {
-	// This is kind of ugly. Really the package name should not
-	// even be included here.
-	if s.Size < 1 || s.P[0] != dwarf.DW_ABRV_FUNCTION {
-		return
-	}
-	e := bytes.IndexByte(s.P, 0)
-	if e == -1 {
-		return
-	}
-	p := bytes.Index(s.P[:e], emptyPkg)
-	if p == -1 {
-		return
-	}
-	pkgprefix := []byte(r.pkgpref)
-	patched := bytes.Replace(s.P[:e], emptyPkg, pkgprefix, -1)
-
-	s.P = append(patched, s.P[e:]...)
-	delta := int64(len(s.P)) - s.Size
-	s.Size = int64(len(s.P))
-	for i := range s.R {
-		r := &s.R[i]
-		if r.Off > int32(e) {
-			r.Off += int32(delta)
-		}
-	}
-}
-
-func (r *objReader) readFull(b []byte) {
-	if r.roObject != nil {
-		copy(b, r.roObject[r.roOffset:])
-		r.roOffset += int64(len(b))
-		return
-	}
-	_, err := io.ReadFull(r.rd, b)
-	if err != nil {
-		log.Fatalf("%s: error reading %s", r.pn, err)
-	}
-}
-
-func (r *objReader) readByte() (byte, error) {
-	if r.roObject != nil {
-		b := r.roObject[r.roOffset]
-		r.roOffset++
-		return b, nil
-	}
-	return r.rd.ReadByte()
-}
-
-func (r *objReader) peek(n int) ([]byte, error) {
-	if r.roObject != nil {
-		return r.roObject[r.roOffset : r.roOffset+int64(n)], nil
-	}
-	return r.rd.Peek(n)
-}
-
-func (r *objReader) readRef() {
-	if c, err := r.readByte(); c != symPrefix || err != nil {
-		log.Fatalf("readSym out of sync")
-	}
-	name := r.readSymName()
-	var v int
-	if abi := r.readInt(); abi == -1 {
-		// Static
-		v = r.localSymVersion
-	} else if abiver := sym.ABIToVersion(obj.ABI(abi)); abiver != -1 {
-		// Note that data symbols are "ABI0", which maps to version 0.
-		v = abiver
-	} else {
-		log.Fatalf("invalid symbol ABI for %q: %d", name, abi)
-	}
-	s := r.syms.Lookup(name, v)
-	r.refs = append(r.refs, s)
-
-	if s == nil || v == r.localSymVersion {
-		return
-	}
-	if s.Name[0] == '$' && len(s.Name) > 5 && s.Type == 0 && len(s.P) == 0 {
-		x, err := strconv.ParseUint(s.Name[5:], 16, 64)
-		if err != nil {
-			log.Panicf("failed to parse $-symbol %s: %v", s.Name, err)
-		}
-		s.Type = sym.SRODATA
-		s.Attr |= sym.AttrLocal
-		switch s.Name[:5] {
-		case "$f32.":
-			if uint64(uint32(x)) != x {
-				log.Panicf("$-symbol %s too large: %d", s.Name, x)
-			}
-			s.AddUint32(r.arch, uint32(x))
-		case "$f64.", "$i64.":
-			s.AddUint64(r.arch, x)
-		default:
-			log.Panicf("unrecognized $-symbol: %s", s.Name)
-		}
-		s.Attr.Set(sym.AttrReachable, false)
-	}
-	if strings.HasPrefix(s.Name, "runtime.gcbits.") {
-		s.Attr |= sym.AttrLocal
-	}
-}
-
-func (r *objReader) readInt64() int64 {
-	uv := uint64(0)
-	for shift := uint(0); ; shift += 7 {
-		if shift >= 64 {
-			log.Fatalf("corrupt input")
-		}
-		c, err := r.readByte()
-		if err != nil {
-			log.Fatalln("error reading input: ", err)
-		}
-		uv |= uint64(c&0x7F) << shift
-		if c&0x80 == 0 {
-			break
-		}
-	}
-
-	return int64(uv>>1) ^ (int64(uv<<63) >> 63)
-}
-
-func (r *objReader) readInt() int {
-	n := r.readInt64()
-	if int64(int(n)) != n {
-		log.Panicf("%v out of range for int", n)
-	}
-	return int(n)
-}
-
-func (r *objReader) readInt32() int32 {
-	n := r.readInt64()
-	if int64(int32(n)) != n {
-		log.Panicf("%v out of range for int32", n)
-	}
-	return int32(n)
-}
-
-func (r *objReader) readInt16() int16 {
-	n := r.readInt64()
-	if int64(int16(n)) != n {
-		log.Panicf("%v out of range for int16", n)
-	}
-	return int16(n)
-}
-
-func (r *objReader) readUint8() uint8 {
-	n := r.readInt64()
-	if int64(uint8(n)) != n {
-		log.Panicf("%v out of range for uint8", n)
-	}
-	return uint8(n)
-}
-
-func (r *objReader) readString() string {
-	n := r.readInt()
-	if cap(r.rdBuf) < n {
-		r.rdBuf = make([]byte, 2*n)
-	}
-	r.readFull(r.rdBuf[:n])
-	return string(r.rdBuf[:n])
-}
-
-func (r *objReader) readData() []byte {
-	n := r.readInt()
-	p := r.data[:n:n]
-	r.data = r.data[n:]
-	return p
-}
-
-func mkROString(rodata []byte) string {
-	if len(rodata) == 0 {
-		return ""
-	}
-
-	var s string
-	hdr := (*unsafeheader.String)(unsafe.Pointer(&s))
-	hdr.Data = unsafe.Pointer(&rodata[0])
-	hdr.Len = len(rodata)
-
-	return s
-}
-
-// readSymName reads a symbol name, replacing all "". with pkg.
-func (r *objReader) readSymName() string {
-	n := r.readInt()
-	if n == 0 {
-		r.readInt64()
-		return ""
-	}
-	if cap(r.rdBuf) < n {
-		r.rdBuf = make([]byte, 2*n)
-	}
-	sOffset := r.roOffset
-	origName, err := r.peek(n)
-	if err == bufio.ErrBufferFull {
-		// Long symbol names are rare but exist. One source is type
-		// symbols for types with long string forms. See #15104.
-		origName = make([]byte, n)
-		r.readFull(origName)
-	} else if err != nil {
-		log.Fatalf("%s: error reading symbol: %v", r.pn, err)
-	}
-	adjName := r.rdBuf[:0]
-	nPkgRefs := 0
-	for {
-		i := bytes.Index(origName, emptyPkg)
-		if i == -1 {
-			var s string
-			if r.roObject != nil && nPkgRefs == 0 {
-				s = mkROString(r.roObject[sOffset : sOffset+int64(n)])
-			} else {
-				s = string(append(adjName, origName...))
-			}
-			// Read past the peeked origName, now that we're done with it,
-			// using the rfBuf (also no longer used) as the scratch space.
-			// TODO: use bufio.Reader.Discard if available instead?
-			if err == nil {
-				r.readFull(r.rdBuf[:n])
-			}
-			r.rdBuf = adjName[:0] // in case 2*n wasn't enough
-			return s
-		}
-		nPkgRefs++
-		adjName = append(adjName, origName[:i]...)
-		adjName = append(adjName, r.pkgpref[:len(r.pkgpref)-1]...)
-		adjName = append(adjName, '.')
-		origName = origName[i+len(emptyPkg):]
-	}
-}
-
-// Reads the index of a symbol reference and resolves it to a symbol
-func (r *objReader) readSymIndex() *sym.Symbol {
-	i := r.readInt()
-	return r.refs[i]
-}
diff --git a/src/cmd/oldlink/internal/ppc64/asm.go b/src/cmd/oldlink/internal/ppc64/asm.go
deleted file mode 100644
index 6b57abf..0000000
--- a/src/cmd/oldlink/internal/ppc64/asm.go
+++ /dev/null
@@ -1,1181 +0,0 @@
-// Inferno utils/5l/asm.c
-// https://bitbucket.org/inferno-os/inferno-os/src/master/utils/5l/asm.c
-//
-//	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 ppc64
-
-import (
-	"cmd/internal/objabi"
-	"cmd/internal/sys"
-	"cmd/oldlink/internal/ld"
-	"cmd/oldlink/internal/sym"
-	"debug/elf"
-	"encoding/binary"
-	"fmt"
-	"log"
-	"strings"
-)
-
-func genplt(ctxt *ld.Link) {
-	// The ppc64 ABI PLT has similar concepts to other
-	// architectures, but is laid out quite differently. When we
-	// see an R_PPC64_REL24 relocation to a dynamic symbol
-	// (indicating that the call needs to go through the PLT), we
-	// generate up to three stubs and reserve a PLT slot.
-	//
-	// 1) The call site will be bl x; nop (where the relocation
-	//    applies to the bl).  We rewrite this to bl x_stub; ld
-	//    r2,24(r1).  The ld is necessary because x_stub will save
-	//    r2 (the TOC pointer) at 24(r1) (the "TOC save slot").
-	//
-	// 2) We reserve space for a pointer in the .plt section (once
-	//    per referenced dynamic function).  .plt is a data
-	//    section filled solely by the dynamic linker (more like
-	//    .plt.got on other architectures).  Initially, the
-	//    dynamic linker will fill each slot with a pointer to the
-	//    corresponding x@plt entry point.
-	//
-	// 3) We generate the "call stub" x_stub (once per dynamic
-	//    function/object file pair).  This saves the TOC in the
-	//    TOC save slot, reads the function pointer from x's .plt
-	//    slot and calls it like any other global entry point
-	//    (including setting r12 to the function address).
-	//
-	// 4) We generate the "symbol resolver stub" x@plt (once per
-	//    dynamic function).  This is solely a branch to the glink
-	//    resolver stub.
-	//
-	// 5) We generate the glink resolver stub (only once).  This
-	//    computes which symbol resolver stub we came through and
-	//    invokes the dynamic resolver via a pointer provided by
-	//    the dynamic linker. This will patch up the .plt slot to
-	//    point directly at the function so future calls go
-	//    straight from the call stub to the real function, and
-	//    then call the function.
-
-	// NOTE: It's possible we could make ppc64 closer to other
-	// architectures: ppc64's .plt is like .plt.got on other
-	// platforms and ppc64's .glink is like .plt on other
-	// platforms.
-
-	// Find all R_PPC64_REL24 relocations that reference dynamic
-	// imports. Reserve PLT entries for these symbols and
-	// generate call stubs. The call stubs need to live in .text,
-	// which is why we need to do this pass this early.
-	//
-	// This assumes "case 1" from the ABI, where the caller needs
-	// us to save and restore the TOC pointer.
-	var stubs []*sym.Symbol
-	for _, s := range ctxt.Textp {
-		for i := range s.R {
-			r := &s.R[i]
-			if r.Type != objabi.ElfRelocOffset+objabi.RelocType(elf.R_PPC64_REL24) || r.Sym.Type != sym.SDYNIMPORT {
-				continue
-			}
-
-			// Reserve PLT entry and generate symbol
-			// resolver
-			addpltsym(ctxt, r.Sym)
-
-			// Generate call stub
-			n := fmt.Sprintf("%s.%s", s.Name, r.Sym.Name)
-
-			stub := ctxt.Syms.Lookup(n, 0)
-			if s.Attr.Reachable() {
-				stub.Attr |= sym.AttrReachable
-			}
-			if stub.Size == 0 {
-				// Need outer to resolve .TOC.
-				stub.Outer = s
-				stubs = append(stubs, stub)
-				gencallstub(ctxt, 1, stub, r.Sym)
-			}
-
-			// Update the relocation to use the call stub
-			r.Sym = stub
-
-			// Restore TOC after bl. The compiler put a
-			// nop here for us to overwrite.
-			const o1 = 0xe8410018 // ld r2,24(r1)
-			ctxt.Arch.ByteOrder.PutUint32(s.P[r.Off+4:], o1)
-		}
-	}
-	// Put call stubs at the beginning (instead of the end).
-	// So when resolving the relocations to calls to the stubs,
-	// the addresses are known and trampolines can be inserted
-	// when necessary.
-	ctxt.Textp = append(stubs, ctxt.Textp...)
-}
-
-func genaddmoduledata(ctxt *ld.Link) {
-	addmoduledata := ctxt.Syms.ROLookup("runtime.addmoduledata", sym.SymVerABI0)
-	if addmoduledata.Type == sym.STEXT && ctxt.BuildMode != ld.BuildModePlugin {
-		return
-	}
-	addmoduledata.Attr |= sym.AttrReachable
-	initfunc := ctxt.Syms.Lookup("go.link.addmoduledata", 0)
-	initfunc.Type = sym.STEXT
-	initfunc.Attr |= sym.AttrLocal
-	initfunc.Attr |= sym.AttrReachable
-	o := func(op uint32) {
-		initfunc.AddUint32(ctxt.Arch, op)
-	}
-	// addis r2, r12, .TOC.-func@ha
-	rel := initfunc.AddRel()
-	rel.Off = int32(initfunc.Size)
-	rel.Siz = 8
-	rel.Sym = ctxt.Syms.Lookup(".TOC.", 0)
-	rel.Sym.Attr |= sym.AttrReachable
-	rel.Type = objabi.R_ADDRPOWER_PCREL
-	o(0x3c4c0000)
-	// addi r2, r2, .TOC.-func@l
-	o(0x38420000)
-	// mflr r31
-	o(0x7c0802a6)
-	// stdu r31, -32(r1)
-	o(0xf801ffe1)
-	// addis r3, r2, local.moduledata@got@ha
-	rel = initfunc.AddRel()
-	rel.Off = int32(initfunc.Size)
-	rel.Siz = 8
-	if s := ctxt.Syms.ROLookup("local.moduledata", 0); s != nil {
-		rel.Sym = s
-	} else if s := ctxt.Syms.ROLookup("local.pluginmoduledata", 0); s != nil {
-		rel.Sym = s
-	} else {
-		rel.Sym = ctxt.Syms.Lookup("runtime.firstmoduledata", 0)
-	}
-	rel.Sym.Attr |= sym.AttrReachable
-	rel.Sym.Attr |= sym.AttrLocal
-	rel.Type = objabi.R_ADDRPOWER_GOT
-	o(0x3c620000)
-	// ld r3, local.moduledata@got@l(r3)
-	o(0xe8630000)
-	// bl runtime.addmoduledata
-	rel = initfunc.AddRel()
-	rel.Off = int32(initfunc.Size)
-	rel.Siz = 4
-	rel.Sym = addmoduledata
-	rel.Type = objabi.R_CALLPOWER
-	o(0x48000001)
-	// nop
-	o(0x60000000)
-	// ld r31, 0(r1)
-	o(0xe8010000)
-	// mtlr r31
-	o(0x7c0803a6)
-	// addi r1,r1,32
-	o(0x38210020)
-	// blr
-	o(0x4e800020)
-
-	if ctxt.BuildMode == ld.BuildModePlugin {
-		ctxt.Textp = append(ctxt.Textp, addmoduledata)
-	}
-	initarray_entry := ctxt.Syms.Lookup("go.link.addmoduledatainit", 0)
-	ctxt.Textp = append(ctxt.Textp, initfunc)
-	initarray_entry.Attr |= sym.AttrReachable
-	initarray_entry.Attr |= sym.AttrLocal
-	initarray_entry.Type = sym.SINITARR
-	initarray_entry.AddAddr(ctxt.Arch, initfunc)
-}
-
-func gentext(ctxt *ld.Link) {
-	if ctxt.DynlinkingGo() {
-		genaddmoduledata(ctxt)
-	}
-
-	if ctxt.LinkMode == ld.LinkInternal {
-		genplt(ctxt)
-	}
-}
-
-// Construct a call stub in stub that calls symbol targ via its PLT
-// entry.
-func gencallstub(ctxt *ld.Link, abicase int, stub *sym.Symbol, targ *sym.Symbol) {
-	if abicase != 1 {
-		// If we see R_PPC64_TOCSAVE or R_PPC64_REL24_NOTOC
-		// relocations, we'll need to implement cases 2 and 3.
-		log.Fatalf("gencallstub only implements case 1 calls")
-	}
-
-	plt := ctxt.Syms.Lookup(".plt", 0)
-
-	stub.Type = sym.STEXT
-
-	// Save TOC pointer in TOC save slot
-	stub.AddUint32(ctxt.Arch, 0xf8410018) // std r2,24(r1)
-
-	// Load the function pointer from the PLT.
-	r := stub.AddRel()
-
-	r.Off = int32(stub.Size)
-	r.Sym = plt
-	r.Add = int64(targ.Plt())
-	r.Siz = 2
-	if ctxt.Arch.ByteOrder == binary.BigEndian {
-		r.Off += int32(r.Siz)
-	}
-	r.Type = objabi.R_POWER_TOC
-	r.Variant = sym.RV_POWER_HA
-	stub.AddUint32(ctxt.Arch, 0x3d820000) // addis r12,r2,targ@plt@toc@ha
-	r = stub.AddRel()
-	r.Off = int32(stub.Size)
-	r.Sym = plt
-	r.Add = int64(targ.Plt())
-	r.Siz = 2
-	if ctxt.Arch.ByteOrder == binary.BigEndian {
-		r.Off += int32(r.Siz)
-	}
-	r.Type = objabi.R_POWER_TOC
-	r.Variant = sym.RV_POWER_LO
-	stub.AddUint32(ctxt.Arch, 0xe98c0000) // ld r12,targ@plt@toc@l(r12)
-
-	// Jump to the loaded pointer
-	stub.AddUint32(ctxt.Arch, 0x7d8903a6) // mtctr r12
-	stub.AddUint32(ctxt.Arch, 0x4e800420) // bctr
-}
-
-func adddynrel(ctxt *ld.Link, s *sym.Symbol, r *sym.Reloc) bool {
-	if ctxt.IsELF {
-		return addelfdynrel(ctxt, s, r)
-	} else if ctxt.HeadType == objabi.Haix {
-		return ld.Xcoffadddynrel(ctxt, s, r)
-	}
-	return false
-}
-func addelfdynrel(ctxt *ld.Link, s *sym.Symbol, r *sym.Reloc) bool {
-	targ := r.Sym
-	r.InitExt()
-
-	switch r.Type {
-	default:
-		if r.Type >= objabi.ElfRelocOffset {
-			ld.Errorf(s, "unexpected relocation type %d (%s)", r.Type, sym.RelocName(ctxt.Arch, r.Type))
-			return false
-		}
-
-		// Handle relocations found in ELF object files.
-	case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_REL24):
-		r.Type = objabi.R_CALLPOWER
-
-		// This is a local call, so the caller isn't setting
-		// up r12 and r2 is the same for the caller and
-		// callee. Hence, we need to go to the local entry
-		// point.  (If we don't do this, the callee will try
-		// to use r12 to compute r2.)
-		r.Add += int64(r.Sym.Localentry()) * 4
-
-		if targ.Type == sym.SDYNIMPORT {
-			// Should have been handled in elfsetupplt
-			ld.Errorf(s, "unexpected R_PPC64_REL24 for dyn import")
-		}
-
-		return true
-
-	case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC_REL32):
-		r.Type = objabi.R_PCREL
-		r.Add += 4
-
-		if targ.Type == sym.SDYNIMPORT {
-			ld.Errorf(s, "unexpected R_PPC_REL32 for dyn import")
-		}
-
-		return true
-
-	case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_ADDR64):
-		r.Type = objabi.R_ADDR
-		if targ.Type == sym.SDYNIMPORT {
-			// These happen in .toc sections
-			ld.Adddynsym(ctxt, targ)
-
-			rela := ctxt.Syms.Lookup(".rela", 0)
-			rela.AddAddrPlus(ctxt.Arch, s, int64(r.Off))
-			rela.AddUint64(ctxt.Arch, ld.ELF64_R_INFO(uint32(targ.Dynid), uint32(elf.R_PPC64_ADDR64)))
-			rela.AddUint64(ctxt.Arch, uint64(r.Add))
-			r.Type = objabi.ElfRelocOffset // ignore during relocsym
-		}
-
-		return true
-
-	case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_TOC16):
-		r.Type = objabi.R_POWER_TOC
-		r.Variant = sym.RV_POWER_LO | sym.RV_CHECK_OVERFLOW
-		return true
-
-	case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_TOC16_LO):
-		r.Type = objabi.R_POWER_TOC
-		r.Variant = sym.RV_POWER_LO
-		return true
-
-	case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_TOC16_HA):
-		r.Type = objabi.R_POWER_TOC
-		r.Variant = sym.RV_POWER_HA | sym.RV_CHECK_OVERFLOW
-		return true
-
-	case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_TOC16_HI):
-		r.Type = objabi.R_POWER_TOC
-		r.Variant = sym.RV_POWER_HI | sym.RV_CHECK_OVERFLOW
-		return true
-
-	case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_TOC16_DS):
-		r.Type = objabi.R_POWER_TOC
-		r.Variant = sym.RV_POWER_DS | sym.RV_CHECK_OVERFLOW
-		return true
-
-	case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_TOC16_LO_DS):
-		r.Type = objabi.R_POWER_TOC
-		r.Variant = sym.RV_POWER_DS
-		return true
-
-	case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_REL16_LO):
-		r.Type = objabi.R_PCREL
-		r.Variant = sym.RV_POWER_LO
-		r.Add += 2 // Compensate for relocation size of 2
-		return true
-
-	case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_REL16_HI):
-		r.Type = objabi.R_PCREL
-		r.Variant = sym.RV_POWER_HI | sym.RV_CHECK_OVERFLOW
-		r.Add += 2
-		return true
-
-	case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_REL16_HA):
-		r.Type = objabi.R_PCREL
-		r.Variant = sym.RV_POWER_HA | sym.RV_CHECK_OVERFLOW
-		r.Add += 2
-		return true
-	}
-
-	// Handle references to ELF symbols from our own object files.
-	if targ.Type != sym.SDYNIMPORT {
-		return true
-	}
-
-	// TODO(austin): Translate our relocations to ELF
-
-	return false
-}
-
-func xcoffreloc1(arch *sys.Arch, out *ld.OutBuf, s *sym.Symbol, r *sym.Reloc, sectoff int64) bool {
-	rs := r.Xsym
-
-	emitReloc := func(v uint16, off uint64) {
-		out.Write64(uint64(sectoff) + off)
-		out.Write32(uint32(rs.Dynid))
-		out.Write16(v)
-	}
-
-	var v uint16
-	switch r.Type {
-	default:
-		return false
-	case objabi.R_ADDR:
-		v = ld.XCOFF_R_POS
-		if r.Siz == 4 {
-			v |= 0x1F << 8
-		} else {
-			v |= 0x3F << 8
-		}
-		emitReloc(v, 0)
-	case objabi.R_ADDRPOWER_TOCREL:
-	case objabi.R_ADDRPOWER_TOCREL_DS:
-		emitReloc(ld.XCOFF_R_TOCU|(0x0F<<8), 2)
-		emitReloc(ld.XCOFF_R_TOCL|(0x0F<<8), 6)
-	case objabi.R_POWER_TLS_LE:
-		emitReloc(ld.XCOFF_R_TLS_LE|0x0F<<8, 2)
-	case objabi.R_CALLPOWER:
-		if r.Siz != 4 {
-			return false
-		}
-		emitReloc(ld.XCOFF_R_RBR|0x19<<8, 0)
-	case objabi.R_XCOFFREF:
-		emitReloc(ld.XCOFF_R_REF|0x3F<<8, 0)
-
-	}
-	return true
-
-}
-
-func elfreloc1(ctxt *ld.Link, r *sym.Reloc, sectoff int64) bool {
-	// Beware that bit0~bit15 start from the third byte of a instruction in Big-Endian machines.
-	if r.Type == objabi.R_ADDR || r.Type == objabi.R_POWER_TLS || r.Type == objabi.R_CALLPOWER {
-	} else {
-		if ctxt.Arch.ByteOrder == binary.BigEndian {
-			sectoff += 2
-		}
-	}
-	ctxt.Out.Write64(uint64(sectoff))
-
-	elfsym := r.Xsym.ElfsymForReloc()
-	switch r.Type {
-	default:
-		return false
-	case objabi.R_ADDR:
-		switch r.Siz {
-		case 4:
-			ctxt.Out.Write64(uint64(elf.R_PPC64_ADDR32) | uint64(elfsym)<<32)
-		case 8:
-			ctxt.Out.Write64(uint64(elf.R_PPC64_ADDR64) | uint64(elfsym)<<32)
-		default:
-			return false
-		}
-	case objabi.R_POWER_TLS:
-		ctxt.Out.Write64(uint64(elf.R_PPC64_TLS) | uint64(elfsym)<<32)
-	case objabi.R_POWER_TLS_LE:
-		ctxt.Out.Write64(uint64(elf.R_PPC64_TPREL16) | uint64(elfsym)<<32)
-	case objabi.R_POWER_TLS_IE:
-		ctxt.Out.Write64(uint64(elf.R_PPC64_GOT_TPREL16_HA) | uint64(elfsym)<<32)
-		ctxt.Out.Write64(uint64(r.Xadd))
-		ctxt.Out.Write64(uint64(sectoff + 4))
-		ctxt.Out.Write64(uint64(elf.R_PPC64_GOT_TPREL16_LO_DS) | uint64(elfsym)<<32)
-	case objabi.R_ADDRPOWER:
-		ctxt.Out.Write64(uint64(elf.R_PPC64_ADDR16_HA) | uint64(elfsym)<<32)
-		ctxt.Out.Write64(uint64(r.Xadd))
-		ctxt.Out.Write64(uint64(sectoff + 4))
-		ctxt.Out.Write64(uint64(elf.R_PPC64_ADDR16_LO) | uint64(elfsym)<<32)
-	case objabi.R_ADDRPOWER_DS:
-		ctxt.Out.Write64(uint64(elf.R_PPC64_ADDR16_HA) | uint64(elfsym)<<32)
-		ctxt.Out.Write64(uint64(r.Xadd))
-		ctxt.Out.Write64(uint64(sectoff + 4))
-		ctxt.Out.Write64(uint64(elf.R_PPC64_ADDR16_LO_DS) | uint64(elfsym)<<32)
-	case objabi.R_ADDRPOWER_GOT:
-		ctxt.Out.Write64(uint64(elf.R_PPC64_GOT16_HA) | uint64(elfsym)<<32)
-		ctxt.Out.Write64(uint64(r.Xadd))
-		ctxt.Out.Write64(uint64(sectoff + 4))
-		ctxt.Out.Write64(uint64(elf.R_PPC64_GOT16_LO_DS) | uint64(elfsym)<<32)
-	case objabi.R_ADDRPOWER_PCREL:
-		ctxt.Out.Write64(uint64(elf.R_PPC64_REL16_HA) | uint64(elfsym)<<32)
-		ctxt.Out.Write64(uint64(r.Xadd))
-		ctxt.Out.Write64(uint64(sectoff + 4))
-		ctxt.Out.Write64(uint64(elf.R_PPC64_REL16_LO) | uint64(elfsym)<<32)
-		r.Xadd += 4
-	case objabi.R_ADDRPOWER_TOCREL:
-		ctxt.Out.Write64(uint64(elf.R_PPC64_TOC16_HA) | uint64(elfsym)<<32)
-		ctxt.Out.Write64(uint64(r.Xadd))
-		ctxt.Out.Write64(uint64(sectoff + 4))
-		ctxt.Out.Write64(uint64(elf.R_PPC64_TOC16_LO) | uint64(elfsym)<<32)
-	case objabi.R_ADDRPOWER_TOCREL_DS:
-		ctxt.Out.Write64(uint64(elf.R_PPC64_TOC16_HA) | uint64(elfsym)<<32)
-		ctxt.Out.Write64(uint64(r.Xadd))
-		ctxt.Out.Write64(uint64(sectoff + 4))
-		ctxt.Out.Write64(uint64(elf.R_PPC64_TOC16_LO_DS) | uint64(elfsym)<<32)
-	case objabi.R_CALLPOWER:
-		if r.Siz != 4 {
-			return false
-		}
-		ctxt.Out.Write64(uint64(elf.R_PPC64_REL24) | uint64(elfsym)<<32)
-
-	}
-	ctxt.Out.Write64(uint64(r.Xadd))
-
-	return true
-}
-
-func elfsetupplt(ctxt *ld.Link) {
-	plt := ctxt.Syms.Lookup(".plt", 0)
-	if plt.Size == 0 {
-		// The dynamic linker stores the address of the
-		// dynamic resolver and the DSO identifier in the two
-		// doublewords at the beginning of the .plt section
-		// before the PLT array. Reserve space for these.
-		plt.Size = 16
-	}
-}
-
-func machoreloc1(arch *sys.Arch, out *ld.OutBuf, s *sym.Symbol, r *sym.Reloc, sectoff int64) bool {
-	return false
-}
-
-// Return the value of .TOC. for symbol s
-func symtoc(ctxt *ld.Link, s *sym.Symbol) int64 {
-	var toc *sym.Symbol
-
-	if s.Outer != nil {
-		toc = ctxt.Syms.ROLookup(".TOC.", int(s.Outer.Version))
-	} else {
-		toc = ctxt.Syms.ROLookup(".TOC.", int(s.Version))
-	}
-
-	if toc == nil {
-		ld.Errorf(s, "TOC-relative relocation in object without .TOC.")
-		return 0
-	}
-
-	return toc.Value
-}
-
-// archreloctoc relocates a TOC relative symbol.
-// If the symbol pointed by this TOC relative symbol is in .data or .bss, the
-// default load instruction can be changed to an addi instruction and the
-// symbol address can be used directly.
-// This code is for AIX only.
-func archreloctoc(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, val int64) int64 {
-	if ctxt.HeadType == objabi.Hlinux {
-		ld.Errorf(s, "archrelocaddr called for %s relocation\n", r.Sym.Name)
-	}
-	var o1, o2 uint32
-
-	o1 = uint32(val >> 32)
-	o2 = uint32(val)
-
-	var t int64
-	useAddi := false
-	const prefix = "TOC."
-	var tarSym *sym.Symbol
-	if strings.HasPrefix(r.Sym.Name, prefix) {
-		tarSym = r.Sym.R[0].Sym
-	} else {
-		ld.Errorf(s, "archreloctoc called for a symbol without TOC anchor")
-	}
-
-	if ctxt.LinkMode == ld.LinkInternal && tarSym != nil && tarSym.Attr.Reachable() && (tarSym.Sect.Seg == &ld.Segdata) {
-		t = ld.Symaddr(tarSym) + r.Add - ctxt.Syms.ROLookup("TOC", 0).Value
-		// change ld to addi in the second instruction
-		o2 = (o2 & 0x03FF0000) | 0xE<<26
-		useAddi = true
-	} else {
-		t = ld.Symaddr(r.Sym) + r.Add - ctxt.Syms.ROLookup("TOC", 0).Value
-	}
-
-	if t != int64(int32(t)) {
-		ld.Errorf(s, "TOC relocation for %s is too big to relocate %s: 0x%x", s.Name, r.Sym, t)
-	}
-
-	if t&0x8000 != 0 {
-		t += 0x10000
-	}
-
-	o1 |= uint32((t >> 16) & 0xFFFF)
-
-	switch r.Type {
-	case objabi.R_ADDRPOWER_TOCREL_DS:
-		if useAddi {
-			o2 |= uint32(t) & 0xFFFF
-		} else {
-			if t&3 != 0 {
-				ld.Errorf(s, "bad DS reloc for %s: %d", s.Name, ld.Symaddr(r.Sym))
-			}
-			o2 |= uint32(t) & 0xFFFC
-		}
-	default:
-		return -1
-	}
-
-	return int64(o1)<<32 | int64(o2)
-}
-
-// archrelocaddr relocates a symbol address.
-// This code is for AIX only.
-func archrelocaddr(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, val int64) int64 {
-	if ctxt.HeadType == objabi.Haix {
-		ld.Errorf(s, "archrelocaddr called for %s relocation\n", r.Sym.Name)
-	}
-	var o1, o2 uint32
-	if ctxt.Arch.ByteOrder == binary.BigEndian {
-		o1 = uint32(val >> 32)
-		o2 = uint32(val)
-	} else {
-		o1 = uint32(val)
-		o2 = uint32(val >> 32)
-	}
-
-	// We are spreading a 31-bit address across two instructions, putting the
-	// high (adjusted) part in the low 16 bits of the first instruction and the
-	// low part in the low 16 bits of the second instruction, or, in the DS case,
-	// bits 15-2 (inclusive) of the address into bits 15-2 of the second
-	// instruction (it is an error in this case if the low 2 bits of the address
-	// are non-zero).
-
-	t := ld.Symaddr(r.Sym) + r.Add
-	if t < 0 || t >= 1<<31 {
-		ld.Errorf(s, "relocation for %s is too big (>=2G): 0x%x", s.Name, ld.Symaddr(r.Sym))
-	}
-	if t&0x8000 != 0 {
-		t += 0x10000
-	}
-
-	switch r.Type {
-	case objabi.R_ADDRPOWER:
-		o1 |= (uint32(t) >> 16) & 0xffff
-		o2 |= uint32(t) & 0xffff
-	case objabi.R_ADDRPOWER_DS:
-		o1 |= (uint32(t) >> 16) & 0xffff
-		if t&3 != 0 {
-			ld.Errorf(s, "bad DS reloc for %s: %d", s.Name, ld.Symaddr(r.Sym))
-		}
-		o2 |= uint32(t) & 0xfffc
-	default:
-		return -1
-	}
-
-	if ctxt.Arch.ByteOrder == binary.BigEndian {
-		return int64(o1)<<32 | int64(o2)
-	}
-	return int64(o2)<<32 | int64(o1)
-}
-
-// resolve direct jump relocation r in s, and add trampoline if necessary
-func trampoline(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol) {
-
-	// Trampolines are created if the branch offset is too large and the linker cannot insert a call stub to handle it.
-	// For internal linking, trampolines are always created for long calls.
-	// For external linking, the linker can insert a call stub to handle a long call, but depends on having the TOC address in
-	// r2.  For those build modes with external linking where the TOC address is not maintained in r2, trampolines must be created.
-	if ctxt.LinkMode == ld.LinkExternal && (ctxt.DynlinkingGo() || ctxt.BuildMode == ld.BuildModeCArchive || ctxt.BuildMode == ld.BuildModeCShared || ctxt.BuildMode == ld.BuildModePIE) {
-		// No trampolines needed since r2 contains the TOC
-		return
-	}
-
-	t := ld.Symaddr(r.Sym) + r.Add - (s.Value + int64(r.Off))
-	switch r.Type {
-	case objabi.R_CALLPOWER:
-
-		// If branch offset is too far then create a trampoline.
-
-		if (ctxt.LinkMode == ld.LinkExternal && s.Sect != r.Sym.Sect) || (ctxt.LinkMode == ld.LinkInternal && int64(int32(t<<6)>>6) != t) || (*ld.FlagDebugTramp > 1 && s.File != r.Sym.File) {
-			var tramp *sym.Symbol
-			for i := 0; ; i++ {
-
-				// Using r.Add as part of the name is significant in functions like duffzero where the call
-				// target is at some offset within the function.  Calls to duff+8 and duff+256 must appear as
-				// distinct trampolines.
-
-				name := r.Sym.Name
-				if r.Add == 0 {
-					name = name + fmt.Sprintf("-tramp%d", i)
-				} else {
-					name = name + fmt.Sprintf("%+x-tramp%d", r.Add, i)
-				}
-
-				// Look up the trampoline in case it already exists
-
-				tramp = ctxt.Syms.Lookup(name, int(r.Sym.Version))
-				if tramp.Value == 0 {
-					break
-				}
-
-				t = ld.Symaddr(tramp) + r.Add - (s.Value + int64(r.Off))
-
-				// With internal linking, the trampoline can be used if it is not too far.
-				// With external linking, the trampoline must be in this section for it to be reused.
-				if (ctxt.LinkMode == ld.LinkInternal && int64(int32(t<<6)>>6) == t) || (ctxt.LinkMode == ld.LinkExternal && s.Sect == tramp.Sect) {
-					break
-				}
-			}
-			if tramp.Type == 0 {
-				if ctxt.DynlinkingGo() || ctxt.BuildMode == ld.BuildModeCArchive || ctxt.BuildMode == ld.BuildModeCShared || ctxt.BuildMode == ld.BuildModePIE {
-					// Should have returned for above cases
-					ld.Errorf(s, "unexpected trampoline for shared or dynamic linking\n")
-				} else {
-					ctxt.AddTramp(tramp)
-					gentramp(ctxt, tramp, r.Sym, r.Add)
-				}
-			}
-			r.Sym = tramp
-			r.Add = 0 // This was folded into the trampoline target address
-			r.Done = false
-		}
-	default:
-		ld.Errorf(s, "trampoline called with non-jump reloc: %d (%s)", r.Type, sym.RelocName(ctxt.Arch, r.Type))
-	}
-}
-
-func gentramp(ctxt *ld.Link, tramp, target *sym.Symbol, offset int64) {
-	tramp.Size = 16 // 4 instructions
-	tramp.P = make([]byte, tramp.Size)
-	t := ld.Symaddr(target) + offset
-	var o1, o2 uint32
-
-	if ctxt.HeadType == objabi.Haix {
-		// On AIX, the address is retrieved with a TOC symbol.
-		// For internal linking, the "Linux" way might still be used.
-		// However, all text symbols are accessed with a TOC symbol as
-		// text relocations aren't supposed to be possible.
-		// So, keep using the external linking way to be more AIX friendly.
-		o1 = uint32(0x3fe20000) // lis r2, toctargetaddr hi
-		o2 = uint32(0xebff0000) // ld r31, toctargetaddr lo
-
-		toctramp := ctxt.Syms.Lookup("TOC."+tramp.Name, 0)
-		toctramp.Type = sym.SXCOFFTOC
-		toctramp.Attr |= sym.AttrReachable
-		toctramp.AddAddr(ctxt.Arch, target)
-
-		tr := tramp.AddRel()
-		tr.Off = 0
-		tr.Type = objabi.R_ADDRPOWER_TOCREL_DS
-		tr.Siz = 8 // generates 2 relocations:  HA + LO
-		tr.Sym = toctramp
-		tr.Add = offset
-	} else {
-		// Used for default build mode for an executable
-		// Address of the call target is generated using
-		// relocation and doesn't depend on r2 (TOC).
-		o1 = uint32(0x3fe00000) // lis r31,targetaddr hi
-		o2 = uint32(0x3bff0000) // addi r31,targetaddr lo
-
-		// With external linking, the target address must be
-		// relocated using LO and HA
-		if ctxt.LinkMode == ld.LinkExternal {
-			tr := tramp.AddRel()
-			tr.Off = 0
-			tr.Type = objabi.R_ADDRPOWER
-			tr.Siz = 8 // generates 2 relocations:  HA + LO
-			tr.Sym = target
-			tr.Add = offset
-
-		} else {
-			// adjustment needed if lo has sign bit set
-			// when using addi to compute address
-			val := uint32((t & 0xffff0000) >> 16)
-			if t&0x8000 != 0 {
-				val += 1
-			}
-			o1 |= val                // hi part of addr
-			o2 |= uint32(t & 0xffff) // lo part of addr
-		}
-	}
-
-	o3 := uint32(0x7fe903a6) // mtctr r31
-	o4 := uint32(0x4e800420) // bctr
-	ctxt.Arch.ByteOrder.PutUint32(tramp.P, o1)
-	ctxt.Arch.ByteOrder.PutUint32(tramp.P[4:], o2)
-	ctxt.Arch.ByteOrder.PutUint32(tramp.P[8:], o3)
-	ctxt.Arch.ByteOrder.PutUint32(tramp.P[12:], o4)
-}
-
-func archreloc(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, val int64) (int64, bool) {
-	if ctxt.LinkMode == ld.LinkExternal {
-		// On AIX, relocations (except TLS ones) must be also done to the
-		// value with the current addresses.
-		switch r.Type {
-		default:
-			if ctxt.HeadType != objabi.Haix {
-				return val, false
-			}
-		case objabi.R_POWER_TLS, objabi.R_POWER_TLS_LE, objabi.R_POWER_TLS_IE:
-			r.Done = false
-			// check Outer is nil, Type is TLSBSS?
-			r.Xadd = r.Add
-			r.Xsym = r.Sym
-			return val, true
-		case objabi.R_ADDRPOWER,
-			objabi.R_ADDRPOWER_DS,
-			objabi.R_ADDRPOWER_TOCREL,
-			objabi.R_ADDRPOWER_TOCREL_DS,
-			objabi.R_ADDRPOWER_GOT,
-			objabi.R_ADDRPOWER_PCREL:
-			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 += ld.Symaddr(rs) - ld.Symaddr(rs.Outer)
-				rs = rs.Outer
-			}
-
-			if rs.Type != sym.SHOSTOBJ && rs.Type != sym.SDYNIMPORT && rs.Type != sym.SUNDEFEXT && rs.Sect == nil {
-				ld.Errorf(s, "missing section for %s", rs.Name)
-			}
-			r.Xsym = rs
-
-			if ctxt.HeadType != objabi.Haix {
-				return val, true
-			}
-		case objabi.R_CALLPOWER:
-			r.Done = false
-			r.Xsym = r.Sym
-			r.Xadd = r.Add
-			if ctxt.HeadType != objabi.Haix {
-				return val, true
-			}
-		}
-	}
-
-	switch r.Type {
-	case objabi.R_CONST:
-		return r.Add, true
-	case objabi.R_GOTOFF:
-		return ld.Symaddr(r.Sym) + r.Add - ld.Symaddr(ctxt.Syms.Lookup(".got", 0)), true
-	case objabi.R_ADDRPOWER_TOCREL, objabi.R_ADDRPOWER_TOCREL_DS:
-		return archreloctoc(ctxt, r, s, val), true
-	case objabi.R_ADDRPOWER, objabi.R_ADDRPOWER_DS:
-		return archrelocaddr(ctxt, r, s, val), true
-	case objabi.R_CALLPOWER:
-		// Bits 6 through 29 = (S + A - P) >> 2
-
-		t := ld.Symaddr(r.Sym) + r.Add - (s.Value + int64(r.Off))
-
-		if t&3 != 0 {
-			ld.Errorf(s, "relocation for %s+%d is not aligned: %d", r.Sym.Name, r.Off, t)
-		}
-		// If branch offset is too far then create a trampoline.
-
-		if int64(int32(t<<6)>>6) != t {
-			ld.Errorf(s, "direct call too far: %s %x", r.Sym.Name, t)
-		}
-		return val | int64(uint32(t)&^0xfc000003), true
-	case objabi.R_POWER_TOC: // S + A - .TOC.
-		return ld.Symaddr(r.Sym) + r.Add - symtoc(ctxt, s), true
-
-	case objabi.R_POWER_TLS_LE:
-		// The thread pointer points 0x7000 bytes after the start of the
-		// thread local storage area as documented in section "3.7.2 TLS
-		// Runtime Handling" of "Power Architecture 64-Bit ELF V2 ABI
-		// Specification".
-		v := r.Sym.Value - 0x7000
-		if ctxt.HeadType == objabi.Haix {
-			// On AIX, the thread pointer points 0x7800 bytes after
-			// the TLS.
-			v -= 0x800
-		}
-		if int64(int16(v)) != v {
-			ld.Errorf(s, "TLS offset out of range %d", v)
-		}
-		return (val &^ 0xffff) | (v & 0xffff), true
-	}
-
-	return val, false
-}
-
-func archrelocvariant(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, t int64) int64 {
-	switch r.Variant & sym.RV_TYPE_MASK {
-	default:
-		ld.Errorf(s, "unexpected relocation variant %d", r.Variant)
-		fallthrough
-
-	case sym.RV_NONE:
-		return t
-
-	case sym.RV_POWER_LO:
-		if r.Variant&sym.RV_CHECK_OVERFLOW != 0 {
-			// Whether to check for signed or unsigned
-			// overflow depends on the instruction
-			var o1 uint32
-			if ctxt.Arch.ByteOrder == binary.BigEndian {
-				o1 = binary.BigEndian.Uint32(s.P[r.Off-2:])
-			} else {
-				o1 = binary.LittleEndian.Uint32(s.P[r.Off:])
-			}
-			switch o1 >> 26 {
-			case 24, // ori
-				26, // xori
-				28: // andi
-				if t>>16 != 0 {
-					goto overflow
-				}
-
-			default:
-				if int64(int16(t)) != t {
-					goto overflow
-				}
-			}
-		}
-
-		return int64(int16(t))
-
-	case sym.RV_POWER_HA:
-		t += 0x8000
-		fallthrough
-
-		// Fallthrough
-	case sym.RV_POWER_HI:
-		t >>= 16
-
-		if r.Variant&sym.RV_CHECK_OVERFLOW != 0 {
-			// Whether to check for signed or unsigned
-			// overflow depends on the instruction
-			var o1 uint32
-			if ctxt.Arch.ByteOrder == binary.BigEndian {
-				o1 = binary.BigEndian.Uint32(s.P[r.Off-2:])
-			} else {
-				o1 = binary.LittleEndian.Uint32(s.P[r.Off:])
-			}
-			switch o1 >> 26 {
-			case 25, // oris
-				27, // xoris
-				29: // andis
-				if t>>16 != 0 {
-					goto overflow
-				}
-
-			default:
-				if int64(int16(t)) != t {
-					goto overflow
-				}
-			}
-		}
-
-		return int64(int16(t))
-
-	case sym.RV_POWER_DS:
-		var o1 uint32
-		if ctxt.Arch.ByteOrder == binary.BigEndian {
-			o1 = uint32(binary.BigEndian.Uint16(s.P[r.Off:]))
-		} else {
-			o1 = uint32(binary.LittleEndian.Uint16(s.P[r.Off:]))
-		}
-		if t&3 != 0 {
-			ld.Errorf(s, "relocation for %s+%d is not aligned: %d", r.Sym.Name, r.Off, t)
-		}
-		if (r.Variant&sym.RV_CHECK_OVERFLOW != 0) && int64(int16(t)) != t {
-			goto overflow
-		}
-		return int64(o1)&0x3 | int64(int16(t))
-	}
-
-overflow:
-	ld.Errorf(s, "relocation for %s+%d is too big: %d", r.Sym.Name, r.Off, t)
-	return t
-}
-
-func addpltsym(ctxt *ld.Link, s *sym.Symbol) {
-	if s.Plt() >= 0 {
-		return
-	}
-
-	ld.Adddynsym(ctxt, s)
-
-	if ctxt.IsELF {
-		plt := ctxt.Syms.Lookup(".plt", 0)
-		rela := ctxt.Syms.Lookup(".rela.plt", 0)
-		if plt.Size == 0 {
-			elfsetupplt(ctxt)
-		}
-
-		// Create the glink resolver if necessary
-		glink := ensureglinkresolver(ctxt)
-
-		// Write symbol resolver stub (just a branch to the
-		// glink resolver stub)
-		r := glink.AddRel()
-
-		r.Sym = glink
-		r.Off = int32(glink.Size)
-		r.Siz = 4
-		r.Type = objabi.R_CALLPOWER
-		glink.AddUint32(ctxt.Arch, 0x48000000) // b .glink
-
-		// In the ppc64 ABI, the dynamic linker is responsible
-		// for writing the entire PLT.  We just need to
-		// reserve 8 bytes for each PLT entry and generate a
-		// JMP_SLOT dynamic relocation for it.
-		//
-		// TODO(austin): ABI v1 is different
-		s.SetPlt(int32(plt.Size))
-
-		plt.Size += 8
-
-		rela.AddAddrPlus(ctxt.Arch, plt, int64(s.Plt()))
-		rela.AddUint64(ctxt.Arch, ld.ELF64_R_INFO(uint32(s.Dynid), uint32(elf.R_PPC64_JMP_SLOT)))
-		rela.AddUint64(ctxt.Arch, 0)
-	} else {
-		ld.Errorf(s, "addpltsym: unsupported binary format")
-	}
-}
-
-// Generate the glink resolver stub if necessary and return the .glink section
-func ensureglinkresolver(ctxt *ld.Link) *sym.Symbol {
-	glink := ctxt.Syms.Lookup(".glink", 0)
-	if glink.Size != 0 {
-		return glink
-	}
-
-	// This is essentially the resolver from the ppc64 ELF ABI.
-	// At entry, r12 holds the address of the symbol resolver stub
-	// for the target routine and the argument registers hold the
-	// arguments for the target routine.
-	//
-	// This stub is PIC, so first get the PC of label 1 into r11.
-	// Other things will be relative to this.
-	glink.AddUint32(ctxt.Arch, 0x7c0802a6) // mflr r0
-	glink.AddUint32(ctxt.Arch, 0x429f0005) // bcl 20,31,1f
-	glink.AddUint32(ctxt.Arch, 0x7d6802a6) // 1: mflr r11
-	glink.AddUint32(ctxt.Arch, 0x7c0803a6) // mtlf r0
-
-	// Compute the .plt array index from the entry point address.
-	// Because this is PIC, everything is relative to label 1b (in
-	// r11):
-	//   r0 = ((r12 - r11) - (res_0 - r11)) / 4 = (r12 - res_0) / 4
-	glink.AddUint32(ctxt.Arch, 0x3800ffd0) // li r0,-(res_0-1b)=-48
-	glink.AddUint32(ctxt.Arch, 0x7c006214) // add r0,r0,r12
-	glink.AddUint32(ctxt.Arch, 0x7c0b0050) // sub r0,r0,r11
-	glink.AddUint32(ctxt.Arch, 0x7800f082) // srdi r0,r0,2
-
-	// r11 = address of the first byte of the PLT
-	r := glink.AddRel()
-
-	r.Off = int32(glink.Size)
-	r.Sym = ctxt.Syms.Lookup(".plt", 0)
-	r.Siz = 8
-	r.Type = objabi.R_ADDRPOWER
-
-	glink.AddUint32(ctxt.Arch, 0x3d600000) // addis r11,0,.plt@ha
-	glink.AddUint32(ctxt.Arch, 0x396b0000) // addi r11,r11,.plt@l
-
-	// Load r12 = dynamic resolver address and r11 = DSO
-	// identifier from the first two doublewords of the PLT.
-	glink.AddUint32(ctxt.Arch, 0xe98b0000) // ld r12,0(r11)
-	glink.AddUint32(ctxt.Arch, 0xe96b0008) // ld r11,8(r11)
-
-	// Jump to the dynamic resolver
-	glink.AddUint32(ctxt.Arch, 0x7d8903a6) // mtctr r12
-	glink.AddUint32(ctxt.Arch, 0x4e800420) // bctr
-
-	// The symbol resolvers must immediately follow.
-	//   res_0:
-
-	// Add DT_PPC64_GLINK .dynamic entry, which points to 32 bytes
-	// before the first symbol resolver stub.
-	s := ctxt.Syms.Lookup(".dynamic", 0)
-
-	ld.Elfwritedynentsymplus(ctxt, s, ld.DT_PPC64_GLINK, glink, glink.Size-32)
-
-	return glink
-}
-
-func asmb(ctxt *ld.Link) {
-	if ctxt.IsELF {
-		ld.Asmbelfsetup()
-	}
-
-	for _, sect := range ld.Segtext.Sections {
-		ctxt.Out.SeekSet(int64(sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff))
-		// Handle additional text sections with Codeblk
-		if sect.Name == ".text" {
-			ld.Codeblk(ctxt, int64(sect.Vaddr), int64(sect.Length))
-		} else {
-			ld.Datblk(ctxt, int64(sect.Vaddr), int64(sect.Length))
-		}
-	}
-
-	if ld.Segrodata.Filelen > 0 {
-		ctxt.Out.SeekSet(int64(ld.Segrodata.Fileoff))
-		ld.Datblk(ctxt, int64(ld.Segrodata.Vaddr), int64(ld.Segrodata.Filelen))
-	}
-	if ld.Segrelrodata.Filelen > 0 {
-		ctxt.Out.SeekSet(int64(ld.Segrelrodata.Fileoff))
-		ld.Datblk(ctxt, int64(ld.Segrelrodata.Vaddr), int64(ld.Segrelrodata.Filelen))
-	}
-
-	ctxt.Out.SeekSet(int64(ld.Segdata.Fileoff))
-	ld.Datblk(ctxt, int64(ld.Segdata.Vaddr), int64(ld.Segdata.Filelen))
-
-	ctxt.Out.SeekSet(int64(ld.Segdwarf.Fileoff))
-	ld.Dwarfblk(ctxt, int64(ld.Segdwarf.Vaddr), int64(ld.Segdwarf.Filelen))
-}
-
-func asmb2(ctxt *ld.Link) {
-	/* output symbol table */
-	ld.Symsize = 0
-
-	ld.Lcsize = 0
-	symo := uint32(0)
-	if !*ld.FlagS {
-		// TODO: rationalize
-		switch ctxt.HeadType {
-		default:
-			if ctxt.IsELF {
-				symo = uint32(ld.Segdwarf.Fileoff + ld.Segdwarf.Filelen)
-				symo = uint32(ld.Rnd(int64(symo), int64(*ld.FlagRound)))
-			}
-
-		case objabi.Hplan9:
-			symo = uint32(ld.Segdata.Fileoff + ld.Segdata.Filelen)
-
-		case objabi.Haix:
-			// Nothing to do
-		}
-
-		ctxt.Out.SeekSet(int64(symo))
-		switch ctxt.HeadType {
-		default:
-			if ctxt.IsELF {
-				ld.Asmelfsym(ctxt)
-				ctxt.Out.Flush()
-				ctxt.Out.Write(ld.Elfstrdat)
-
-				if ctxt.LinkMode == ld.LinkExternal {
-					ld.Elfemitreloc(ctxt)
-				}
-			}
-
-		case objabi.Hplan9:
-			ld.Asmplan9sym(ctxt)
-			ctxt.Out.Flush()
-
-			sym := ctxt.Syms.Lookup("pclntab", 0)
-			if sym != nil {
-				ld.Lcsize = int32(len(sym.P))
-				ctxt.Out.Write(sym.P)
-				ctxt.Out.Flush()
-			}
-
-		case objabi.Haix:
-			// symtab must be added once sections have been created in ld.Asmbxcoff
-			ctxt.Out.Flush()
-		}
-	}
-
-	ctxt.Out.SeekSet(0)
-	switch ctxt.HeadType {
-	default:
-	case objabi.Hplan9: /* plan 9 */
-		ctxt.Out.Write32(0x647)                      /* magic */
-		ctxt.Out.Write32(uint32(ld.Segtext.Filelen)) /* sizes */
-		ctxt.Out.Write32(uint32(ld.Segdata.Filelen))
-		ctxt.Out.Write32(uint32(ld.Segdata.Length - ld.Segdata.Filelen))
-		ctxt.Out.Write32(uint32(ld.Symsize))          /* nsyms */
-		ctxt.Out.Write32(uint32(ld.Entryvalue(ctxt))) /* va of entry */
-		ctxt.Out.Write32(0)
-		ctxt.Out.Write32(uint32(ld.Lcsize))
-
-	case objabi.Hlinux,
-		objabi.Hfreebsd,
-		objabi.Hnetbsd,
-		objabi.Hopenbsd:
-		ld.Asmbelf(ctxt, int64(symo))
-
-	case objabi.Haix:
-		fileoff := uint32(ld.Segdwarf.Fileoff + ld.Segdwarf.Filelen)
-		fileoff = uint32(ld.Rnd(int64(fileoff), int64(*ld.FlagRound)))
-		ld.Asmbxcoff(ctxt, int64(fileoff))
-	}
-
-	ctxt.Out.Flush()
-	if *ld.FlagC {
-		fmt.Printf("textsize=%d\n", ld.Segtext.Filelen)
-		fmt.Printf("datsize=%d\n", ld.Segdata.Filelen)
-		fmt.Printf("bsssize=%d\n", ld.Segdata.Length-ld.Segdata.Filelen)
-		fmt.Printf("symsize=%d\n", ld.Symsize)
-		fmt.Printf("lcsize=%d\n", ld.Lcsize)
-		fmt.Printf("total=%d\n", ld.Segtext.Filelen+ld.Segdata.Length+uint64(ld.Symsize)+uint64(ld.Lcsize))
-	}
-}
diff --git a/src/cmd/oldlink/internal/ppc64/l.go b/src/cmd/oldlink/internal/ppc64/l.go
deleted file mode 100644
index e8d3b68..0000000
--- a/src/cmd/oldlink/internal/ppc64/l.go
+++ /dev/null
@@ -1,74 +0,0 @@
-// Inferno utils/5l/asm.c
-// https://bitbucket.org/inferno-os/inferno-os/src/master/utils/5l/asm.c
-//
-//	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 ppc64
-
-// Writing object files.
-
-// cmd/9l/l.h from Vita Nuova.
-//
-//	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-2008 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-2008 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.
-
-const (
-	maxAlign  = 32 // max data alignment
-	minAlign  = 1  // min data alignment
-	funcAlign = 16
-)
-
-/* Used by ../internal/ld/dwarf.go */
-const (
-	dwarfRegSP = 1
-	dwarfRegLR = 65
-)
diff --git a/src/cmd/oldlink/internal/ppc64/obj.go b/src/cmd/oldlink/internal/ppc64/obj.go
deleted file mode 100644
index f508fbd..0000000
--- a/src/cmd/oldlink/internal/ppc64/obj.go
+++ /dev/null
@@ -1,106 +0,0 @@
-// Inferno utils/5l/obj.c
-// https://bitbucket.org/inferno-os/inferno-os/src/master/utils/5l/obj.c
-//
-//	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 ppc64
-
-import (
-	"cmd/internal/objabi"
-	"cmd/internal/sys"
-	"cmd/oldlink/internal/ld"
-)
-
-func Init() (*sys.Arch, ld.Arch) {
-	arch := sys.ArchPPC64
-	if objabi.GOARCH == "ppc64le" {
-		arch = sys.ArchPPC64LE
-	}
-
-	theArch := ld.Arch{
-		Funcalign:  funcAlign,
-		Maxalign:   maxAlign,
-		Minalign:   minAlign,
-		Dwarfregsp: dwarfRegSP,
-		Dwarfreglr: dwarfRegLR,
-
-		Adddynrel:        adddynrel,
-		Archinit:         archinit,
-		Archreloc:        archreloc,
-		Archrelocvariant: archrelocvariant,
-		Asmb:             asmb,
-		Asmb2:            asmb2,
-		Elfreloc1:        elfreloc1,
-		Elfsetupplt:      elfsetupplt,
-		Gentext:          gentext,
-		Trampoline:       trampoline,
-		Machoreloc1:      machoreloc1,
-		Xcoffreloc1:      xcoffreloc1,
-
-		// TODO(austin): ABI v1 uses /usr/lib/ld.so.1,
-		Linuxdynld: "/lib64/ld64.so.1",
-
-		Freebsddynld:   "XXX",
-		Openbsddynld:   "XXX",
-		Netbsddynld:    "XXX",
-		Dragonflydynld: "XXX",
-		Solarisdynld:   "XXX",
-	}
-
-	return arch, theArch
-}
-
-func archinit(ctxt *ld.Link) {
-	switch ctxt.HeadType {
-	default:
-		ld.Exitf("unknown -H option: %v", ctxt.HeadType)
-
-	case objabi.Hplan9: /* plan 9 */
-		ld.HEADR = 32
-
-		if *ld.FlagTextAddr == -1 {
-			*ld.FlagTextAddr = 4128
-		}
-		if *ld.FlagRound == -1 {
-			*ld.FlagRound = 4096
-		}
-
-	case objabi.Hlinux: /* ppc64 elf */
-		ld.Elfinit(ctxt)
-		ld.HEADR = ld.ELFRESERVE
-		if *ld.FlagTextAddr == -1 {
-			*ld.FlagTextAddr = 0x10000 + int64(ld.HEADR)
-		}
-		if *ld.FlagRound == -1 {
-			*ld.FlagRound = 0x10000
-		}
-
-	case objabi.Haix:
-		ld.Xcoffinit(ctxt)
-	}
-}
diff --git a/src/cmd/oldlink/internal/riscv64/asm.go b/src/cmd/oldlink/internal/riscv64/asm.go
deleted file mode 100644
index f4db32d..0000000
--- a/src/cmd/oldlink/internal/riscv64/asm.go
+++ /dev/null
@@ -1,168 +0,0 @@
-// Copyright 2019 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 riscv64
-
-import (
-	"cmd/internal/obj/riscv"
-	"cmd/internal/objabi"
-	"cmd/internal/sys"
-	"cmd/oldlink/internal/ld"
-	"cmd/oldlink/internal/sym"
-	"fmt"
-	"log"
-)
-
-func gentext(ctxt *ld.Link) {
-}
-
-func adddynrela(ctxt *ld.Link, rel *sym.Symbol, s *sym.Symbol, r *sym.Reloc) {
-	log.Fatalf("adddynrela not implemented")
-}
-
-func adddynrel(ctxt *ld.Link, s *sym.Symbol, r *sym.Reloc) bool {
-	log.Fatalf("adddynrel not implemented")
-	return false
-}
-
-func elfreloc1(ctxt *ld.Link, r *sym.Reloc, sectoff int64) bool {
-	log.Fatalf("elfreloc1")
-	return false
-}
-
-func elfsetupplt(ctxt *ld.Link) {
-	log.Fatalf("elfsetuplt")
-}
-
-func machoreloc1(arch *sys.Arch, out *ld.OutBuf, s *sym.Symbol, r *sym.Reloc, sectoff int64) bool {
-	log.Fatalf("machoreloc1 not implemented")
-	return false
-}
-
-func archreloc(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, val int64) (int64, bool) {
-	switch r.Type {
-	case objabi.R_CALLRISCV:
-		// Nothing to do.
-		return val, true
-
-	case objabi.R_RISCV_PCREL_ITYPE, objabi.R_RISCV_PCREL_STYPE:
-		pc := s.Value + int64(r.Off)
-		off := ld.Symaddr(r.Sym) + r.Add - pc
-
-		// Generate AUIPC and second instruction immediates.
-		low, high, err := riscv.Split32BitImmediate(off)
-		if err != nil {
-			ld.Errorf(s, "R_RISCV_PCREL_ relocation does not fit in 32-bits: %d", off)
-		}
-
-		auipcImm, err := riscv.EncodeUImmediate(high)
-		if err != nil {
-			ld.Errorf(s, "cannot encode R_RISCV_PCREL_ AUIPC relocation offset for %s: %v", r.Sym.Name, err)
-		}
-
-		var secondImm, secondImmMask int64
-		switch r.Type {
-		case objabi.R_RISCV_PCREL_ITYPE:
-			secondImmMask = riscv.ITypeImmMask
-			secondImm, err = riscv.EncodeIImmediate(low)
-			if err != nil {
-				ld.Errorf(s, "cannot encode R_RISCV_PCREL_ITYPE I-type instruction relocation offset for %s: %v", r.Sym.Name, err)
-			}
-		case objabi.R_RISCV_PCREL_STYPE:
-			secondImmMask = riscv.STypeImmMask
-			secondImm, err = riscv.EncodeSImmediate(low)
-			if err != nil {
-				ld.Errorf(s, "cannot encode R_RISCV_PCREL_STYPE S-type instruction relocation offset for %s: %v", r.Sym.Name, err)
-			}
-		default:
-			panic(fmt.Sprintf("Unknown relocation type: %v", r.Type))
-		}
-
-		auipc := int64(uint32(val))
-		second := int64(uint32(val >> 32))
-
-		auipc = (auipc &^ riscv.UTypeImmMask) | int64(uint32(auipcImm))
-		second = (second &^ secondImmMask) | int64(uint32(secondImm))
-
-		return second<<32 | auipc, true
-	}
-
-	return val, false
-}
-
-func archrelocvariant(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, t int64) int64 {
-	log.Fatalf("archrelocvariant")
-	return -1
-}
-
-func asmb(ctxt *ld.Link) {
-	if ctxt.IsELF {
-		ld.Asmbelfsetup()
-	}
-
-	sect := ld.Segtext.Sections[0]
-	ctxt.Out.SeekSet(int64(sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff))
-	ld.Codeblk(ctxt, int64(sect.Vaddr), int64(sect.Length))
-	for _, sect = range ld.Segtext.Sections[1:] {
-		ctxt.Out.SeekSet(int64(sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff))
-		ld.Datblk(ctxt, int64(sect.Vaddr), int64(sect.Length))
-	}
-
-	if ld.Segrodata.Filelen > 0 {
-		ctxt.Out.SeekSet(int64(ld.Segrodata.Fileoff))
-		ld.Datblk(ctxt, int64(ld.Segrodata.Vaddr), int64(ld.Segrodata.Filelen))
-	}
-	if ld.Segrelrodata.Filelen > 0 {
-		ctxt.Out.SeekSet(int64(ld.Segrelrodata.Fileoff))
-		ld.Datblk(ctxt, int64(ld.Segrelrodata.Vaddr), int64(ld.Segrelrodata.Filelen))
-	}
-
-	ctxt.Out.SeekSet(int64(ld.Segdata.Fileoff))
-	ld.Datblk(ctxt, int64(ld.Segdata.Vaddr), int64(ld.Segdata.Filelen))
-
-	ctxt.Out.SeekSet(int64(ld.Segdwarf.Fileoff))
-	ld.Dwarfblk(ctxt, int64(ld.Segdwarf.Vaddr), int64(ld.Segdwarf.Filelen))
-}
-
-func asmb2(ctxt *ld.Link) {
-	ld.Symsize = 0
-	ld.Lcsize = 0
-	symo := uint32(0)
-
-	if !*ld.FlagS {
-		if !ctxt.IsELF {
-			ld.Errorf(nil, "unsupported executable format")
-		}
-
-		symo = uint32(ld.Segdwarf.Fileoff + ld.Segdwarf.Filelen)
-		symo = uint32(ld.Rnd(int64(symo), int64(*ld.FlagRound)))
-		ctxt.Out.SeekSet(int64(symo))
-
-		ld.Asmelfsym(ctxt)
-		ctxt.Out.Flush()
-		ctxt.Out.Write(ld.Elfstrdat)
-
-		if ctxt.LinkMode == ld.LinkExternal {
-			ld.Elfemitreloc(ctxt)
-		}
-	}
-
-	ctxt.Out.SeekSet(0)
-	switch ctxt.HeadType {
-	case objabi.Hlinux:
-		ld.Asmbelf(ctxt, int64(symo))
-	default:
-		ld.Errorf(nil, "unsupported operating system")
-	}
-	ctxt.Out.Flush()
-
-	if *ld.FlagC {
-		fmt.Printf("textsize=%d\n", ld.Segtext.Filelen)
-		fmt.Printf("datsize=%d\n", ld.Segdata.Filelen)
-		fmt.Printf("bsssize=%d\n", ld.Segdata.Length-ld.Segdata.Filelen)
-		fmt.Printf("symsize=%d\n", ld.Symsize)
-		fmt.Printf("lcsize=%d\n", ld.Lcsize)
-		fmt.Printf("total=%d\n", ld.Segtext.Filelen+ld.Segdata.Length+uint64(ld.Symsize)+uint64(ld.Lcsize))
-	}
-}
diff --git a/src/cmd/oldlink/internal/riscv64/l.go b/src/cmd/oldlink/internal/riscv64/l.go
deleted file mode 100644
index a302657..0000000
--- a/src/cmd/oldlink/internal/riscv64/l.go
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright 2019 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 riscv64
-
-const (
-	maxAlign  = 32 // max data alignment
-	minAlign  = 1
-	funcAlign = 8
-
-	dwarfRegLR = 1
-	dwarfRegSP = 2
-)
diff --git a/src/cmd/oldlink/internal/riscv64/obj.go b/src/cmd/oldlink/internal/riscv64/obj.go
deleted file mode 100644
index a6a5adb..0000000
--- a/src/cmd/oldlink/internal/riscv64/obj.go
+++ /dev/null
@@ -1,60 +0,0 @@
-// Copyright 2019 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 riscv64
-
-import (
-	"cmd/internal/objabi"
-	"cmd/internal/sys"
-	"cmd/oldlink/internal/ld"
-)
-
-func Init() (*sys.Arch, ld.Arch) {
-	arch := sys.ArchRISCV64
-
-	theArch := ld.Arch{
-		Funcalign:  funcAlign,
-		Maxalign:   maxAlign,
-		Minalign:   minAlign,
-		Dwarfregsp: dwarfRegSP,
-		Dwarfreglr: dwarfRegLR,
-
-		Adddynrel:        adddynrel,
-		Archinit:         archinit,
-		Archreloc:        archreloc,
-		Archrelocvariant: archrelocvariant,
-		Asmb:             asmb,
-		Asmb2:            asmb2,
-		Elfreloc1:        elfreloc1,
-		Elfsetupplt:      elfsetupplt,
-		Gentext:          gentext,
-		Machoreloc1:      machoreloc1,
-
-		Linuxdynld: "/lib/ld.so.1",
-
-		Freebsddynld:   "XXX",
-		Netbsddynld:    "XXX",
-		Openbsddynld:   "XXX",
-		Dragonflydynld: "XXX",
-		Solarisdynld:   "XXX",
-	}
-
-	return arch, theArch
-}
-
-func archinit(ctxt *ld.Link) {
-	switch ctxt.HeadType {
-	case objabi.Hlinux:
-		ld.Elfinit(ctxt)
-		ld.HEADR = ld.ELFRESERVE
-		if *ld.FlagTextAddr == -1 {
-			*ld.FlagTextAddr = 0x10000 + int64(ld.HEADR)
-		}
-		if *ld.FlagRound == -1 {
-			*ld.FlagRound = 0x10000
-		}
-	default:
-		ld.Exitf("unknown -H option: %v", ctxt.HeadType)
-	}
-}
diff --git a/src/cmd/oldlink/internal/s390x/asm.go b/src/cmd/oldlink/internal/s390x/asm.go
deleted file mode 100644
index 23cda2a..0000000
--- a/src/cmd/oldlink/internal/s390x/asm.go
+++ /dev/null
@@ -1,574 +0,0 @@
-// Inferno utils/5l/asm.c
-// https://bitbucket.org/inferno-os/inferno-os/src/master/utils/5l/asm.c
-//
-//	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 s390x
-
-import (
-	"cmd/internal/objabi"
-	"cmd/internal/sys"
-	"cmd/oldlink/internal/ld"
-	"cmd/oldlink/internal/sym"
-	"debug/elf"
-	"fmt"
-)
-
-// gentext generates assembly to append the local moduledata to the global
-// moduledata linked list at initialization time. This is only done if the runtime
-// is in a different module.
-//
-// <go.link.addmoduledata>:
-// 	larl  %r2, <local.moduledata>
-// 	jg    <runtime.addmoduledata@plt>
-//	undef
-//
-// The job of appending the moduledata is delegated to runtime.addmoduledata.
-func gentext(ctxt *ld.Link) {
-	if !ctxt.DynlinkingGo() {
-		return
-	}
-	addmoduledata := ctxt.Syms.Lookup("runtime.addmoduledata", 0)
-	if addmoduledata.Type == sym.STEXT && ctxt.BuildMode != ld.BuildModePlugin {
-		// we're linking a module containing the runtime -> no need for
-		// an init function
-		return
-	}
-	addmoduledata.Attr |= sym.AttrReachable
-	initfunc := ctxt.Syms.Lookup("go.link.addmoduledata", 0)
-	initfunc.Type = sym.STEXT
-	initfunc.Attr |= sym.AttrLocal
-	initfunc.Attr |= sym.AttrReachable
-
-	// larl %r2, <local.moduledata>
-	initfunc.AddUint8(0xc0)
-	initfunc.AddUint8(0x20)
-	lmd := initfunc.AddRel()
-	lmd.InitExt()
-	lmd.Off = int32(initfunc.Size)
-	lmd.Siz = 4
-	lmd.Sym = ctxt.Moduledata
-	lmd.Type = objabi.R_PCREL
-	lmd.Variant = sym.RV_390_DBL
-	lmd.Add = 2 + int64(lmd.Siz)
-	initfunc.AddUint32(ctxt.Arch, 0)
-
-	// jg <runtime.addmoduledata[@plt]>
-	initfunc.AddUint8(0xc0)
-	initfunc.AddUint8(0xf4)
-	rel := initfunc.AddRel()
-	rel.InitExt()
-	rel.Off = int32(initfunc.Size)
-	rel.Siz = 4
-	rel.Sym = ctxt.Syms.Lookup("runtime.addmoduledata", 0)
-	rel.Type = objabi.R_CALL
-	rel.Variant = sym.RV_390_DBL
-	rel.Add = 2 + int64(rel.Siz)
-	initfunc.AddUint32(ctxt.Arch, 0)
-
-	// undef (for debugging)
-	initfunc.AddUint32(ctxt.Arch, 0)
-	if ctxt.BuildMode == ld.BuildModePlugin {
-		ctxt.Textp = append(ctxt.Textp, addmoduledata)
-	}
-	ctxt.Textp = append(ctxt.Textp, initfunc)
-	initarray_entry := ctxt.Syms.Lookup("go.link.addmoduledatainit", 0)
-	initarray_entry.Attr |= sym.AttrLocal
-	initarray_entry.Attr |= sym.AttrReachable
-	initarray_entry.Type = sym.SINITARR
-	initarray_entry.AddAddr(ctxt.Arch, initfunc)
-}
-
-func adddynrel(ctxt *ld.Link, s *sym.Symbol, r *sym.Reloc) bool {
-	targ := r.Sym
-	r.InitExt()
-
-	switch r.Type {
-	default:
-		if r.Type >= objabi.ElfRelocOffset {
-			ld.Errorf(s, "unexpected relocation type %d", r.Type)
-			return false
-		}
-
-		// Handle relocations found in ELF object files.
-	case objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_12),
-		objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_GOT12):
-		ld.Errorf(s, "s390x 12-bit relocations have not been implemented (relocation type %d)", r.Type-objabi.ElfRelocOffset)
-		return false
-
-	case objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_8),
-		objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_16),
-		objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_32),
-		objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_64):
-		if targ.Type == sym.SDYNIMPORT {
-			ld.Errorf(s, "unexpected R_390_nn relocation for dynamic symbol %s", targ.Name)
-		}
-		r.Type = objabi.R_ADDR
-		return true
-
-	case objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_PC16),
-		objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_PC32),
-		objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_PC64):
-		if targ.Type == sym.SDYNIMPORT {
-			ld.Errorf(s, "unexpected R_390_PCnn relocation for dynamic symbol %s", targ.Name)
-		}
-		// TODO(mwhudson): the test of VisibilityHidden here probably doesn't make
-		// sense and should be removed when someone has thought about it properly.
-		if (targ.Type == 0 || targ.Type == sym.SXREF) && !targ.Attr.VisibilityHidden() {
-			ld.Errorf(s, "unknown symbol %s in pcrel", targ.Name)
-		}
-		r.Type = objabi.R_PCREL
-		r.Add += int64(r.Siz)
-		return true
-
-	case objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_GOT16),
-		objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_GOT32),
-		objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_GOT64):
-		ld.Errorf(s, "unimplemented S390x relocation: %v", r.Type-objabi.ElfRelocOffset)
-		return true
-
-	case objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_PLT16DBL),
-		objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_PLT32DBL):
-		r.Type = objabi.R_PCREL
-		r.Variant = sym.RV_390_DBL
-		r.Add += int64(r.Siz)
-		if targ.Type == sym.SDYNIMPORT {
-			addpltsym(ctxt, targ)
-			r.Sym = ctxt.Syms.Lookup(".plt", 0)
-			r.Add += int64(targ.Plt())
-		}
-		return true
-
-	case objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_PLT32),
-		objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_PLT64):
-		r.Type = objabi.R_PCREL
-		r.Add += int64(r.Siz)
-		if targ.Type == sym.SDYNIMPORT {
-			addpltsym(ctxt, targ)
-			r.Sym = ctxt.Syms.Lookup(".plt", 0)
-			r.Add += int64(targ.Plt())
-		}
-		return true
-
-	case objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_COPY):
-		ld.Errorf(s, "unimplemented S390x relocation: %v", r.Type-objabi.ElfRelocOffset)
-		return false
-
-	case objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_GLOB_DAT):
-		ld.Errorf(s, "unimplemented S390x relocation: %v", r.Type-objabi.ElfRelocOffset)
-		return false
-
-	case objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_JMP_SLOT):
-		ld.Errorf(s, "unimplemented S390x relocation: %v", r.Type-objabi.ElfRelocOffset)
-		return false
-
-	case objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_RELATIVE):
-		ld.Errorf(s, "unimplemented S390x relocation: %v", r.Type-objabi.ElfRelocOffset)
-		return false
-
-	case objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_GOTOFF):
-		if targ.Type == sym.SDYNIMPORT {
-			ld.Errorf(s, "unexpected R_390_GOTOFF relocation for dynamic symbol %s", targ.Name)
-		}
-		r.Type = objabi.R_GOTOFF
-		return true
-
-	case objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_GOTPC):
-		r.Type = objabi.R_PCREL
-		r.Sym = ctxt.Syms.Lookup(".got", 0)
-		r.Add += int64(r.Siz)
-		return true
-
-	case objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_PC16DBL),
-		objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_PC32DBL):
-		r.Type = objabi.R_PCREL
-		r.Variant = sym.RV_390_DBL
-		r.Add += int64(r.Siz)
-		if targ.Type == sym.SDYNIMPORT {
-			ld.Errorf(s, "unexpected R_390_PCnnDBL relocation for dynamic symbol %s", targ.Name)
-		}
-		return true
-
-	case objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_GOTPCDBL):
-		r.Type = objabi.R_PCREL
-		r.Variant = sym.RV_390_DBL
-		r.Sym = ctxt.Syms.Lookup(".got", 0)
-		r.Add += int64(r.Siz)
-		return true
-
-	case objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_GOTENT):
-		addgotsym(ctxt, targ)
-
-		r.Type = objabi.R_PCREL
-		r.Variant = sym.RV_390_DBL
-		r.Sym = ctxt.Syms.Lookup(".got", 0)
-		r.Add += int64(targ.Got())
-		r.Add += int64(r.Siz)
-		return true
-	}
-	// Handle references to ELF symbols from our own object files.
-	if targ.Type != sym.SDYNIMPORT {
-		return true
-	}
-
-	return false
-}
-
-func elfreloc1(ctxt *ld.Link, r *sym.Reloc, sectoff int64) bool {
-	ctxt.Out.Write64(uint64(sectoff))
-
-	elfsym := r.Xsym.ElfsymForReloc()
-	switch r.Type {
-	default:
-		return false
-	case objabi.R_TLS_LE:
-		switch r.Siz {
-		default:
-			return false
-		case 4:
-			// WARNING - silently ignored by linker in ELF64
-			ctxt.Out.Write64(uint64(elf.R_390_TLS_LE32) | uint64(elfsym)<<32)
-		case 8:
-			// WARNING - silently ignored by linker in ELF32
-			ctxt.Out.Write64(uint64(elf.R_390_TLS_LE64) | uint64(elfsym)<<32)
-		}
-	case objabi.R_TLS_IE:
-		switch r.Siz {
-		default:
-			return false
-		case 4:
-			ctxt.Out.Write64(uint64(elf.R_390_TLS_IEENT) | uint64(elfsym)<<32)
-		}
-	case objabi.R_ADDR:
-		switch r.Siz {
-		default:
-			return false
-		case 4:
-			ctxt.Out.Write64(uint64(elf.R_390_32) | uint64(elfsym)<<32)
-		case 8:
-			ctxt.Out.Write64(uint64(elf.R_390_64) | uint64(elfsym)<<32)
-		}
-	case objabi.R_GOTPCREL:
-		if r.Siz == 4 {
-			ctxt.Out.Write64(uint64(elf.R_390_GOTENT) | uint64(elfsym)<<32)
-		} else {
-			return false
-		}
-	case objabi.R_PCREL, objabi.R_PCRELDBL, objabi.R_CALL:
-		elfrel := elf.R_390_NONE
-		isdbl := r.Variant&sym.RV_TYPE_MASK == sym.RV_390_DBL
-		// TODO(mundaym): all DBL style relocations should be
-		// signalled using the variant - see issue 14218.
-		switch r.Type {
-		case objabi.R_PCRELDBL, objabi.R_CALL:
-			isdbl = true
-		}
-		if r.Xsym.Type == sym.SDYNIMPORT && (r.Xsym.ElfType() == elf.STT_FUNC || r.Type == objabi.R_CALL) {
-			if isdbl {
-				switch r.Siz {
-				case 2:
-					elfrel = elf.R_390_PLT16DBL
-				case 4:
-					elfrel = elf.R_390_PLT32DBL
-				}
-			} else {
-				switch r.Siz {
-				case 4:
-					elfrel = elf.R_390_PLT32
-				case 8:
-					elfrel = elf.R_390_PLT64
-				}
-			}
-		} else {
-			if isdbl {
-				switch r.Siz {
-				case 2:
-					elfrel = elf.R_390_PC16DBL
-				case 4:
-					elfrel = elf.R_390_PC32DBL
-				}
-			} else {
-				switch r.Siz {
-				case 2:
-					elfrel = elf.R_390_PC16
-				case 4:
-					elfrel = elf.R_390_PC32
-				case 8:
-					elfrel = elf.R_390_PC64
-				}
-			}
-		}
-		if elfrel == elf.R_390_NONE {
-			return false // unsupported size/dbl combination
-		}
-		ctxt.Out.Write64(uint64(elfrel) | uint64(elfsym)<<32)
-	}
-
-	ctxt.Out.Write64(uint64(r.Xadd))
-	return true
-}
-
-func elfsetupplt(ctxt *ld.Link) {
-	plt := ctxt.Syms.Lookup(".plt", 0)
-	got := ctxt.Syms.Lookup(".got", 0)
-	if plt.Size == 0 {
-		// stg     %r1,56(%r15)
-		plt.AddUint8(0xe3)
-		plt.AddUint8(0x10)
-		plt.AddUint8(0xf0)
-		plt.AddUint8(0x38)
-		plt.AddUint8(0x00)
-		plt.AddUint8(0x24)
-		// larl    %r1,_GLOBAL_OFFSET_TABLE_
-		plt.AddUint8(0xc0)
-		plt.AddUint8(0x10)
-		plt.AddPCRelPlus(ctxt.Arch, got, 6)
-		// mvc     48(8,%r15),8(%r1)
-		plt.AddUint8(0xd2)
-		plt.AddUint8(0x07)
-		plt.AddUint8(0xf0)
-		plt.AddUint8(0x30)
-		plt.AddUint8(0x10)
-		plt.AddUint8(0x08)
-		// lg      %r1,16(%r1)
-		plt.AddUint8(0xe3)
-		plt.AddUint8(0x10)
-		plt.AddUint8(0x10)
-		plt.AddUint8(0x10)
-		plt.AddUint8(0x00)
-		plt.AddUint8(0x04)
-		// br      %r1
-		plt.AddUint8(0x07)
-		plt.AddUint8(0xf1)
-		// nopr    %r0
-		plt.AddUint8(0x07)
-		plt.AddUint8(0x00)
-		// nopr    %r0
-		plt.AddUint8(0x07)
-		plt.AddUint8(0x00)
-		// nopr    %r0
-		plt.AddUint8(0x07)
-		plt.AddUint8(0x00)
-
-		// assume got->size == 0 too
-		got.AddAddrPlus(ctxt.Arch, ctxt.Syms.Lookup(".dynamic", 0), 0)
-
-		got.AddUint64(ctxt.Arch, 0)
-		got.AddUint64(ctxt.Arch, 0)
-	}
-}
-
-func machoreloc1(arch *sys.Arch, out *ld.OutBuf, s *sym.Symbol, r *sym.Reloc, sectoff int64) bool {
-	return false
-}
-
-func archreloc(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, val int64) (int64, bool) {
-	if ctxt.LinkMode == ld.LinkExternal {
-		return val, false
-	}
-
-	switch r.Type {
-	case objabi.R_CONST:
-		return r.Add, true
-	case objabi.R_GOTOFF:
-		return ld.Symaddr(r.Sym) + r.Add - ld.Symaddr(ctxt.Syms.Lookup(".got", 0)), true
-	}
-
-	return val, false
-}
-
-func archrelocvariant(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, t int64) int64 {
-	switch r.Variant & sym.RV_TYPE_MASK {
-	default:
-		ld.Errorf(s, "unexpected relocation variant %d", r.Variant)
-		return t
-
-	case sym.RV_NONE:
-		return t
-
-	case sym.RV_390_DBL:
-		if (t & 1) != 0 {
-			ld.Errorf(s, "%s+%v is not 2-byte aligned", r.Sym.Name, r.Sym.Value)
-		}
-		return t >> 1
-	}
-}
-
-func addpltsym(ctxt *ld.Link, s *sym.Symbol) {
-	if s.Plt() >= 0 {
-		return
-	}
-
-	ld.Adddynsym(ctxt, s)
-
-	if ctxt.IsELF {
-		plt := ctxt.Syms.Lookup(".plt", 0)
-		got := ctxt.Syms.Lookup(".got", 0)
-		rela := ctxt.Syms.Lookup(".rela.plt", 0)
-		if plt.Size == 0 {
-			elfsetupplt(ctxt)
-		}
-		// larl    %r1,_GLOBAL_OFFSET_TABLE_+index
-
-		plt.AddUint8(0xc0)
-		plt.AddUint8(0x10)
-		plt.AddPCRelPlus(ctxt.Arch, got, got.Size+6) // need variant?
-
-		// add to got: pointer to current pos in plt
-		got.AddAddrPlus(ctxt.Arch, plt, plt.Size+8) // weird but correct
-		// lg      %r1,0(%r1)
-		plt.AddUint8(0xe3)
-		plt.AddUint8(0x10)
-		plt.AddUint8(0x10)
-		plt.AddUint8(0x00)
-		plt.AddUint8(0x00)
-		plt.AddUint8(0x04)
-		// br      %r1
-		plt.AddUint8(0x07)
-		plt.AddUint8(0xf1)
-		// basr    %r1,%r0
-		plt.AddUint8(0x0d)
-		plt.AddUint8(0x10)
-		// lgf     %r1,12(%r1)
-		plt.AddUint8(0xe3)
-		plt.AddUint8(0x10)
-		plt.AddUint8(0x10)
-		plt.AddUint8(0x0c)
-		plt.AddUint8(0x00)
-		plt.AddUint8(0x14)
-		// jg .plt
-		plt.AddUint8(0xc0)
-		plt.AddUint8(0xf4)
-
-		plt.AddUint32(ctxt.Arch, uint32(-((plt.Size - 2) >> 1))) // roll-your-own relocation
-		//.plt index
-		plt.AddUint32(ctxt.Arch, uint32(rela.Size)) // rela size before current entry
-
-		// rela
-		rela.AddAddrPlus(ctxt.Arch, got, got.Size-8)
-
-		rela.AddUint64(ctxt.Arch, ld.ELF64_R_INFO(uint32(s.Dynid), uint32(elf.R_390_JMP_SLOT)))
-		rela.AddUint64(ctxt.Arch, 0)
-
-		s.SetPlt(int32(plt.Size - 32))
-
-	} else {
-		ld.Errorf(s, "addpltsym: unsupported binary format")
-	}
-}
-
-func addgotsym(ctxt *ld.Link, s *sym.Symbol) {
-	if s.Got() >= 0 {
-		return
-	}
-
-	ld.Adddynsym(ctxt, s)
-	got := ctxt.Syms.Lookup(".got", 0)
-	s.SetGot(int32(got.Size))
-	got.AddUint64(ctxt.Arch, 0)
-
-	if ctxt.IsELF {
-		rela := ctxt.Syms.Lookup(".rela", 0)
-		rela.AddAddrPlus(ctxt.Arch, got, int64(s.Got()))
-		rela.AddUint64(ctxt.Arch, ld.ELF64_R_INFO(uint32(s.Dynid), uint32(elf.R_390_GLOB_DAT)))
-		rela.AddUint64(ctxt.Arch, 0)
-	} else {
-		ld.Errorf(s, "addgotsym: unsupported binary format")
-	}
-}
-
-func asmb(ctxt *ld.Link) {
-	if ctxt.IsELF {
-		ld.Asmbelfsetup()
-	}
-
-	sect := ld.Segtext.Sections[0]
-	ctxt.Out.SeekSet(int64(sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff))
-	ld.Codeblk(ctxt, int64(sect.Vaddr), int64(sect.Length))
-	for _, sect = range ld.Segtext.Sections[1:] {
-		ctxt.Out.SeekSet(int64(sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff))
-		ld.Datblk(ctxt, int64(sect.Vaddr), int64(sect.Length))
-	}
-
-	if ld.Segrodata.Filelen > 0 {
-		ctxt.Out.SeekSet(int64(ld.Segrodata.Fileoff))
-		ld.Datblk(ctxt, int64(ld.Segrodata.Vaddr), int64(ld.Segrodata.Filelen))
-	}
-	if ld.Segrelrodata.Filelen > 0 {
-		ctxt.Out.SeekSet(int64(ld.Segrelrodata.Fileoff))
-		ld.Datblk(ctxt, int64(ld.Segrelrodata.Vaddr), int64(ld.Segrelrodata.Filelen))
-	}
-
-	ctxt.Out.SeekSet(int64(ld.Segdata.Fileoff))
-	ld.Datblk(ctxt, int64(ld.Segdata.Vaddr), int64(ld.Segdata.Filelen))
-
-	ctxt.Out.SeekSet(int64(ld.Segdwarf.Fileoff))
-	ld.Dwarfblk(ctxt, int64(ld.Segdwarf.Vaddr), int64(ld.Segdwarf.Filelen))
-}
-
-func asmb2(ctxt *ld.Link) {
-	/* output symbol table */
-	ld.Symsize = 0
-
-	ld.Lcsize = 0
-	symo := uint32(0)
-	if !*ld.FlagS {
-		if !ctxt.IsELF {
-			ld.Errorf(nil, "unsupported executable format")
-		}
-		symo = uint32(ld.Segdwarf.Fileoff + ld.Segdwarf.Filelen)
-		symo = uint32(ld.Rnd(int64(symo), int64(*ld.FlagRound)))
-
-		ctxt.Out.SeekSet(int64(symo))
-		ld.Asmelfsym(ctxt)
-		ctxt.Out.Flush()
-		ctxt.Out.Write(ld.Elfstrdat)
-
-		if ctxt.LinkMode == ld.LinkExternal {
-			ld.Elfemitreloc(ctxt)
-		}
-	}
-
-	ctxt.Out.SeekSet(0)
-	switch ctxt.HeadType {
-	default:
-		ld.Errorf(nil, "unsupported operating system")
-	case objabi.Hlinux:
-		ld.Asmbelf(ctxt, int64(symo))
-	}
-
-	ctxt.Out.Flush()
-	if *ld.FlagC {
-		fmt.Printf("textsize=%d\n", ld.Segtext.Filelen)
-		fmt.Printf("datsize=%d\n", ld.Segdata.Filelen)
-		fmt.Printf("bsssize=%d\n", ld.Segdata.Length-ld.Segdata.Filelen)
-		fmt.Printf("symsize=%d\n", ld.Symsize)
-		fmt.Printf("lcsize=%d\n", ld.Lcsize)
-		fmt.Printf("total=%d\n", ld.Segtext.Filelen+ld.Segdata.Length+uint64(ld.Symsize)+uint64(ld.Lcsize))
-	}
-}
diff --git a/src/cmd/oldlink/internal/s390x/l.go b/src/cmd/oldlink/internal/s390x/l.go
deleted file mode 100644
index f040587..0000000
--- a/src/cmd/oldlink/internal/s390x/l.go
+++ /dev/null
@@ -1,74 +0,0 @@
-// Inferno utils/5l/asm.c
-// https://bitbucket.org/inferno-os/inferno-os/src/master/utils/5l/asm.c
-//
-//	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 s390x
-
-// Writing object files.
-
-// cmd/9l/l.h from Vita Nuova.
-//
-//	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-2008 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-2008 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.
-
-const (
-	maxAlign  = 32 // max data alignment
-	minAlign  = 2  // min data alignment
-	funcAlign = 16
-)
-
-/* Used by ../internal/ld/dwarf.go */
-const (
-	dwarfRegSP = 15
-	dwarfRegLR = 14
-)
diff --git a/src/cmd/oldlink/internal/s390x/obj.go b/src/cmd/oldlink/internal/s390x/obj.go
deleted file mode 100644
index 7317cdc..0000000
--- a/src/cmd/oldlink/internal/s390x/obj.go
+++ /dev/null
@@ -1,88 +0,0 @@
-// Inferno utils/5l/obj.c
-// https://bitbucket.org/inferno-os/inferno-os/src/master/utils/5l/obj.c
-//
-//	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 s390x
-
-import (
-	"cmd/internal/objabi"
-	"cmd/internal/sys"
-	"cmd/oldlink/internal/ld"
-)
-
-func Init() (*sys.Arch, ld.Arch) {
-	arch := sys.ArchS390X
-
-	theArch := ld.Arch{
-		Funcalign:  funcAlign,
-		Maxalign:   maxAlign,
-		Minalign:   minAlign,
-		Dwarfregsp: dwarfRegSP,
-		Dwarfreglr: dwarfRegLR,
-
-		Adddynrel:        adddynrel,
-		Archinit:         archinit,
-		Archreloc:        archreloc,
-		Archrelocvariant: archrelocvariant,
-		Asmb:             asmb,  // in asm.go
-		Asmb2:            asmb2, // in asm.go
-		Elfreloc1:        elfreloc1,
-		Elfsetupplt:      elfsetupplt,
-		Gentext:          gentext,
-		Machoreloc1:      machoreloc1,
-
-		Linuxdynld: "/lib64/ld64.so.1",
-
-		// not relevant for s390x
-		Freebsddynld:   "XXX",
-		Openbsddynld:   "XXX",
-		Netbsddynld:    "XXX",
-		Dragonflydynld: "XXX",
-		Solarisdynld:   "XXX",
-	}
-
-	return arch, theArch
-}
-
-func archinit(ctxt *ld.Link) {
-	switch ctxt.HeadType {
-	default:
-		ld.Exitf("unknown -H option: %v", ctxt.HeadType)
-
-	case objabi.Hlinux: // s390x ELF
-		ld.Elfinit(ctxt)
-		ld.HEADR = ld.ELFRESERVE
-		if *ld.FlagTextAddr == -1 {
-			*ld.FlagTextAddr = 0x10000 + int64(ld.HEADR)
-		}
-		if *ld.FlagRound == -1 {
-			*ld.FlagRound = 0x10000
-		}
-	}
-}
diff --git a/src/cmd/oldlink/internal/sym/attribute.go b/src/cmd/oldlink/internal/sym/attribute.go
deleted file mode 100644
index 4b69bf3..0000000
--- a/src/cmd/oldlink/internal/sym/attribute.go
+++ /dev/null
@@ -1,117 +0,0 @@
-// Copyright 2017 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 sym
-
-// Attribute is a set of common symbol attributes.
-type Attribute int32
-
-const (
-	// AttrDuplicateOK marks a symbol that can be present in multiple object
-	// files.
-	AttrDuplicateOK Attribute = 1 << iota
-	// AttrExternal marks function symbols loaded from host object files.
-	AttrExternal
-	// AttrNoSplit marks functions that cannot split the stack; the linker
-	// cares because it checks that there are no call chains of nosplit
-	// functions that require more than StackLimit bytes (see
-	// lib.go:dostkcheck)
-	AttrNoSplit
-	// AttrReachable marks symbols that are transitively referenced from the
-	// entry points. Unreachable symbols are not written to the output.
-	AttrReachable
-	// AttrCgoExportDynamic and AttrCgoExportStatic mark symbols referenced
-	// by directives written by cgo (in response to //export directives in
-	// the source).
-	AttrCgoExportDynamic
-	AttrCgoExportStatic
-	// AttrSpecial marks symbols that do not have their address (i.e. Value)
-	// computed by the usual mechanism of data.go:dodata() &
-	// data.go:address().
-	AttrSpecial
-	// AttrStackCheck is used by dostkcheck to only check each NoSplit
-	// function's stack usage once.
-	AttrStackCheck
-	// AttrNotInSymbolTable marks symbols that are not written to the symbol table.
-	AttrNotInSymbolTable
-	// AttrOnList marks symbols that are on some list (such as the list of
-	// all text symbols, or one of the lists of data symbols) and is
-	// consulted to avoid bugs where a symbol is put on a list twice.
-	AttrOnList
-	// AttrLocal marks symbols that are only visible within the module
-	// (executable or shared library) being linked. Only relevant when
-	// dynamically linking Go code.
-	AttrLocal
-	// AttrReflectMethod marks certain methods from the reflect package that
-	// can be used to call arbitrary methods. If no symbol with this bit set
-	// is marked as reachable, more dead code elimination can be done.
-	AttrReflectMethod
-	// AttrMakeTypelink Amarks types that should be added to the typelink
-	// table. See typelinks.go:typelinks().
-	AttrMakeTypelink
-	// AttrShared marks symbols compiled with the -shared option.
-	AttrShared
-	// AttrVisibilityHidden symbols are ELF symbols with
-	// visibility set to STV_HIDDEN. They become local symbols in
-	// the final executable. Only relevant when internally linking
-	// on an ELF platform.
-	AttrVisibilityHidden
-	// AttrSubSymbol mostly means that the symbol appears on the Sub list of some
-	// other symbol.  Unfortunately, it's not 100% reliable; at least, it's not set
-	// correctly for the .TOC. symbol in Link.dodata.  Usually the Outer field of the
-	// symbol points to the symbol whose list it is on, but that it is not set for the
-	// symbols added to .windynamic in initdynimport in pe.go.
-	//
-	// TODO(mwhudson): fix the inconsistencies noticed above.
-	//
-	// Sub lists are used when loading host objects (sections from the host object
-	// become regular linker symbols and symbols go on the Sub list of their section)
-	// and for constructing the global offset table when internally linking a dynamic
-	// executable.
-	//
-	// TODO(mwhudson): perhaps a better name for this is AttrNonGoSymbol.
-	AttrSubSymbol
-	// AttrContainer is set on text symbols that are present as the .Outer for some
-	// other symbol.
-	AttrContainer
-	// AttrTopFrame means that the function is an entry point and unwinders
-	// should stop when they hit this function.
-	AttrTopFrame
-	// AttrReadOnly indicates whether the symbol's content (Symbol.P) is backed by
-	// read-only memory.
-	AttrReadOnly
-	// 19 attributes defined so far.
-)
-
-func (a Attribute) DuplicateOK() bool      { return a&AttrDuplicateOK != 0 }
-func (a Attribute) External() bool         { return a&AttrExternal != 0 }
-func (a Attribute) NoSplit() bool          { return a&AttrNoSplit != 0 }
-func (a Attribute) Reachable() bool        { return a&AttrReachable != 0 }
-func (a Attribute) CgoExportDynamic() bool { return a&AttrCgoExportDynamic != 0 }
-func (a Attribute) CgoExportStatic() bool  { return a&AttrCgoExportStatic != 0 }
-func (a Attribute) Special() bool          { return a&AttrSpecial != 0 }
-func (a Attribute) StackCheck() bool       { return a&AttrStackCheck != 0 }
-func (a Attribute) NotInSymbolTable() bool { return a&AttrNotInSymbolTable != 0 }
-func (a Attribute) OnList() bool           { return a&AttrOnList != 0 }
-func (a Attribute) Local() bool            { return a&AttrLocal != 0 }
-func (a Attribute) ReflectMethod() bool    { return a&AttrReflectMethod != 0 }
-func (a Attribute) MakeTypelink() bool     { return a&AttrMakeTypelink != 0 }
-func (a Attribute) Shared() bool           { return a&AttrShared != 0 }
-func (a Attribute) VisibilityHidden() bool { return a&AttrVisibilityHidden != 0 }
-func (a Attribute) SubSymbol() bool        { return a&AttrSubSymbol != 0 }
-func (a Attribute) Container() bool        { return a&AttrContainer != 0 }
-func (a Attribute) TopFrame() bool         { return a&AttrTopFrame != 0 }
-func (a Attribute) ReadOnly() bool         { return a&AttrReadOnly != 0 }
-
-func (a Attribute) CgoExport() bool {
-	return a.CgoExportDynamic() || a.CgoExportStatic()
-}
-
-func (a *Attribute) Set(flag Attribute, value bool) {
-	if value {
-		*a |= flag
-	} else {
-		*a &^= flag
-	}
-}
diff --git a/src/cmd/oldlink/internal/sym/compilation_unit.go b/src/cmd/oldlink/internal/sym/compilation_unit.go
deleted file mode 100644
index 02fb0cf..0000000
--- a/src/cmd/oldlink/internal/sym/compilation_unit.go
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2019 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 sym
-
-import "cmd/internal/dwarf"
-
-// CompilationUnit is an abstraction used by DWARF to represent a chunk of
-// debug-related data. We create a CompilationUnit per Object file in a
-// library (so, one for all the Go code, one for each assembly file, etc.).
-type CompilationUnit struct {
-	Pkg            string        // The package name, eg ("fmt", or "runtime")
-	Lib            *Library      // Our library
-	Consts         *Symbol       // Package constants DIEs
-	PCs            []dwarf.Range // PC ranges, relative to Textp[0]
-	DWInfo         *dwarf.DWDie  // CU root DIE
-	FuncDIEs       []*Symbol     // Function DIE subtrees
-	AbsFnDIEs      []*Symbol     // Abstract function DIE subtrees
-	RangeSyms      []*Symbol     // Symbols for debug_range
-	Textp          []*Symbol     // Text symbols in this CU
-	DWARFFileTable []string      // The file table used to generate the .debug_lines
-}
diff --git a/src/cmd/oldlink/internal/sym/library.go b/src/cmd/oldlink/internal/sym/library.go
deleted file mode 100644
index 4f2023b..0000000
--- a/src/cmd/oldlink/internal/sym/library.go
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2017 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 sym
-
-type Library struct {
-	Objref        string
-	Srcref        string
-	File          string
-	Pkg           string
-	Shlib         string
-	Hash          string
-	ImportStrings []string
-	Imports       []*Library
-	Textp         []*Symbol // text symbols defined in this library
-	DupTextSyms   []*Symbol // dupok text symbols defined in this library
-	Main          bool
-	Safe          bool
-	Units         []*CompilationUnit
-}
-
-func (l Library) String() string {
-	return l.Pkg
-}
diff --git a/src/cmd/oldlink/internal/sym/reloc.go b/src/cmd/oldlink/internal/sym/reloc.go
deleted file mode 100644
index 4809db8..0000000
--- a/src/cmd/oldlink/internal/sym/reloc.go
+++ /dev/null
@@ -1,128 +0,0 @@
-// Copyright 2017 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 sym
-
-import (
-	"cmd/internal/objabi"
-	"cmd/internal/sys"
-	"debug/elf"
-)
-
-// Reloc is a relocation.
-//
-// The typical Reloc rewrites part of a symbol at offset Off to address Sym.
-// A Reloc is stored in a slice on the Symbol it rewrites.
-//
-// Relocations are generated by the compiler as the type
-// cmd/internal/obj.Reloc, which is encoded into the object file wire
-// format and decoded by the linker into this type. A separate type is
-// used to hold linker-specific state about the relocation.
-//
-// Some relocations are created by cmd/link.
-type Reloc struct {
-	Off       int32            // offset to rewrite
-	Siz       uint8            // number of bytes to rewrite, 1, 2, or 4
-	Done      bool             // set to true when relocation is complete
-	Type      objabi.RelocType // the relocation type
-	Add       int64            // addend
-	Sym       *Symbol          // symbol the relocation addresses
-	*relocExt                  // extra fields (see below), may be nil, call InitExt before use
-}
-
-// relocExt contains extra fields in Reloc that are used only in
-// certain cases.
-type relocExt struct {
-	Xadd    int64        // addend passed to external linker
-	Xsym    *Symbol      // symbol passed to external linker
-	Variant RelocVariant // variation on Type, currently used only on PPC64 and S390X
-}
-
-func (r *Reloc) InitExt() {
-	if r.relocExt == nil {
-		r.relocExt = new(relocExt)
-	}
-}
-
-// RelocVariant is a linker-internal variation on a relocation.
-type RelocVariant uint8
-
-const (
-	RV_NONE RelocVariant = iota
-	RV_POWER_LO
-	RV_POWER_HI
-	RV_POWER_HA
-	RV_POWER_DS
-
-	// RV_390_DBL is a s390x-specific relocation variant that indicates that
-	// the value to be placed into the relocatable field should first be
-	// divided by 2.
-	RV_390_DBL
-
-	RV_CHECK_OVERFLOW RelocVariant = 1 << 7
-	RV_TYPE_MASK      RelocVariant = RV_CHECK_OVERFLOW - 1
-)
-
-func RelocName(arch *sys.Arch, r objabi.RelocType) string {
-	// We didn't have some relocation types at Go1.4.
-	// Uncomment code when we include those in bootstrap code.
-
-	switch {
-	case r >= objabi.MachoRelocOffset: // Mach-O
-		// nr := (r - objabi.MachoRelocOffset)>>1
-		// switch ctxt.Arch.Family {
-		// case sys.AMD64:
-		// 	return macho.RelocTypeX86_64(nr).String()
-		// case sys.ARM:
-		// 	return macho.RelocTypeARM(nr).String()
-		// case sys.ARM64:
-		// 	return macho.RelocTypeARM64(nr).String()
-		// case sys.I386:
-		// 	return macho.RelocTypeGeneric(nr).String()
-		// default:
-		// 	panic("unreachable")
-		// }
-	case r >= objabi.ElfRelocOffset: // ELF
-		nr := r - objabi.ElfRelocOffset
-		switch arch.Family {
-		case sys.AMD64:
-			return elf.R_X86_64(nr).String()
-		case sys.ARM:
-			return elf.R_ARM(nr).String()
-		case sys.ARM64:
-			return elf.R_AARCH64(nr).String()
-		case sys.I386:
-			return elf.R_386(nr).String()
-		case sys.MIPS, sys.MIPS64:
-			return elf.R_MIPS(nr).String()
-		case sys.PPC64:
-			return elf.R_PPC64(nr).String()
-		case sys.S390X:
-			return elf.R_390(nr).String()
-		default:
-			panic("unreachable")
-		}
-	}
-
-	return r.String()
-}
-
-// RelocByOff implements sort.Interface for sorting relocations by offset.
-type RelocByOff []Reloc
-
-func (x RelocByOff) Len() int { return len(x) }
-
-func (x RelocByOff) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
-
-func (x RelocByOff) Less(i, j int) bool {
-	a := &x[i]
-	b := &x[j]
-	if a.Off < b.Off {
-		return true
-	}
-	if a.Off > b.Off {
-		return false
-	}
-	return false
-}
diff --git a/src/cmd/oldlink/internal/sym/segment.go b/src/cmd/oldlink/internal/sym/segment.go
deleted file mode 100644
index 395679a..0000000
--- a/src/cmd/oldlink/internal/sym/segment.go
+++ /dev/null
@@ -1,58 +0,0 @@
-// Inferno utils/8l/asm.c
-// https://bitbucket.org/inferno-os/inferno-os/src/master/utils/8l/asm.c
-//
-//	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 sym
-
-// Terrible but standard terminology.
-// A segment describes a block of file to load into memory.
-// A section further describes the pieces of that block for
-// use in debuggers and such.
-
-type Segment struct {
-	Rwx      uint8  // permission as usual unix bits (5 = r-x etc)
-	Vaddr    uint64 // virtual address
-	Length   uint64 // length in memory
-	Fileoff  uint64 // file offset
-	Filelen  uint64 // length on disk
-	Sections []*Section
-}
-
-type Section struct {
-	Rwx     uint8
-	Extnum  int16
-	Align   int32
-	Name    string
-	Vaddr   uint64
-	Length  uint64
-	Seg     *Segment
-	Elfsect interface{} // an *ld.ElfShdr
-	Reloff  uint64
-	Rellen  uint64
-}
diff --git a/src/cmd/oldlink/internal/sym/sizeof_test.go b/src/cmd/oldlink/internal/sym/sizeof_test.go
deleted file mode 100644
index e6e3916..0000000
--- a/src/cmd/oldlink/internal/sym/sizeof_test.go
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright 2018 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 sym
-
-import (
-	"reflect"
-	"testing"
-	"unsafe"
-)
-
-// Assert that the size of important structures do not change unexpectedly.
-
-func TestSizeof(t *testing.T) {
-	const nbit = unsafe.Sizeof(uintptr(0)) * 8
-	const _64bit = nbit == 64
-
-	var tests = []struct {
-		val    interface{} // type as a value
-		_32bit uintptr     // size on 32bit platforms
-		_64bit uintptr     // size on 64bit platforms
-	}{
-		{Symbol{}, 108, 176},
-	}
-
-	for _, tt := range tests {
-		want := tt._32bit
-		if _64bit {
-			want = tt._64bit
-		}
-		got := reflect.TypeOf(tt.val).Size()
-		if want != got {
-			t.Errorf("%d bit unsafe.Sizeof(%T) = %d, want %d", nbit, tt.val, got, want)
-		}
-	}
-}
diff --git a/src/cmd/oldlink/internal/sym/symbol.go b/src/cmd/oldlink/internal/sym/symbol.go
deleted file mode 100644
index 2756acd..0000000
--- a/src/cmd/oldlink/internal/sym/symbol.go
+++ /dev/null
@@ -1,543 +0,0 @@
-// Copyright 2017 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 sym
-
-import (
-	"cmd/internal/obj"
-	"cmd/internal/objabi"
-	"cmd/internal/sys"
-	"debug/elf"
-	"fmt"
-	"log"
-)
-
-// Symbol is an entry in the symbol table.
-type Symbol struct {
-	Name        string
-	Type        SymKind
-	Version     int16
-	Attr        Attribute
-	Dynid       int32
-	Align       int32
-	Elfsym      int32
-	LocalElfsym int32
-	Value       int64
-	Size        int64
-	Sub         *Symbol
-	Outer       *Symbol
-	Gotype      *Symbol
-	File        string // actually package!
-	auxinfo     *AuxSymbol
-	Sect        *Section
-	FuncInfo    *FuncInfo
-	Unit        *CompilationUnit
-	// P contains the raw symbol data.
-	P []byte
-	R []Reloc
-}
-
-// AuxSymbol contains less-frequently used sym.Symbol fields.
-type AuxSymbol struct {
-	extname    string
-	dynimplib  string
-	dynimpvers string
-	localentry uint8
-	plt        int32
-	got        int32
-	// ElfType is set for symbols read from shared libraries by ldshlibsyms. It
-	// is not set for symbols defined by the packages being linked or by symbols
-	// read by ldelf (and so is left as elf.STT_NOTYPE).
-	elftype elf.SymType
-}
-
-const (
-	SymVerABI0        = 0
-	SymVerABIInternal = 1
-	SymVerStatic      = 10 // Minimum version used by static (file-local) syms
-)
-
-func ABIToVersion(abi obj.ABI) int {
-	switch abi {
-	case obj.ABI0:
-		return SymVerABI0
-	case obj.ABIInternal:
-		return SymVerABIInternal
-	}
-	return -1
-}
-
-func VersionToABI(v int) (obj.ABI, bool) {
-	switch v {
-	case SymVerABI0:
-		return obj.ABI0, true
-	case SymVerABIInternal:
-		return obj.ABIInternal, true
-	}
-	return ^obj.ABI(0), false
-}
-
-func (s *Symbol) String() string {
-	if s.Version == 0 {
-		return s.Name
-	}
-	return fmt.Sprintf("%s<%d>", s.Name, s.Version)
-}
-
-func (s *Symbol) IsFileLocal() bool {
-	return s.Version >= SymVerStatic
-}
-
-func (s *Symbol) ElfsymForReloc() int32 {
-	// If putelfsym created a local version of this symbol, use that in all
-	// relocations.
-	if s.LocalElfsym != 0 {
-		return s.LocalElfsym
-	} else {
-		return s.Elfsym
-	}
-}
-
-func (s *Symbol) Length(_ interface{}) int64 {
-	return s.Size
-}
-
-func (s *Symbol) Grow(siz int64) {
-	if int64(int(siz)) != siz {
-		log.Fatalf("symgrow size %d too long", siz)
-	}
-	if int64(len(s.P)) >= siz {
-		return
-	}
-	if cap(s.P) < int(siz) {
-		p := make([]byte, 2*(siz+1))
-		s.P = append(p[:0], s.P...)
-	}
-	s.P = s.P[:siz]
-}
-
-func (s *Symbol) AddBytes(bytes []byte) int64 {
-	if s.Type == 0 {
-		s.Type = SDATA
-	}
-	s.Attr |= AttrReachable
-	s.P = append(s.P, bytes...)
-	s.Size = int64(len(s.P))
-
-	return s.Size
-}
-
-func (s *Symbol) AddUint8(v uint8) int64 {
-	off := s.Size
-	if s.Type == 0 {
-		s.Type = SDATA
-	}
-	s.Attr |= AttrReachable
-	s.Size++
-	s.P = append(s.P, v)
-
-	return off
-}
-
-func (s *Symbol) AddUint16(arch *sys.Arch, v uint16) int64 {
-	return s.AddUintXX(arch, uint64(v), 2)
-}
-
-func (s *Symbol) AddUint32(arch *sys.Arch, v uint32) int64 {
-	return s.AddUintXX(arch, uint64(v), 4)
-}
-
-func (s *Symbol) AddUint64(arch *sys.Arch, v uint64) int64 {
-	return s.AddUintXX(arch, v, 8)
-}
-
-func (s *Symbol) AddUint(arch *sys.Arch, v uint64) int64 {
-	return s.AddUintXX(arch, v, arch.PtrSize)
-}
-
-func (s *Symbol) SetUint8(arch *sys.Arch, r int64, v uint8) int64 {
-	return s.setUintXX(arch, r, uint64(v), 1)
-}
-
-func (s *Symbol) SetUint16(arch *sys.Arch, r int64, v uint16) int64 {
-	return s.setUintXX(arch, r, uint64(v), 2)
-}
-
-func (s *Symbol) SetUint32(arch *sys.Arch, r int64, v uint32) int64 {
-	return s.setUintXX(arch, r, uint64(v), 4)
-}
-
-func (s *Symbol) SetUint(arch *sys.Arch, r int64, v uint64) int64 {
-	return s.setUintXX(arch, r, v, int64(arch.PtrSize))
-}
-
-func (s *Symbol) addAddrPlus(arch *sys.Arch, t *Symbol, add int64, typ objabi.RelocType) int64 {
-	if s.Type == 0 {
-		s.Type = SDATA
-	}
-	s.Attr |= AttrReachable
-	i := s.Size
-	s.Size += int64(arch.PtrSize)
-	s.Grow(s.Size)
-	r := s.AddRel()
-	r.Sym = t
-	r.Off = int32(i)
-	r.Siz = uint8(arch.PtrSize)
-	r.Type = typ
-	r.Add = add
-	return i + int64(r.Siz)
-}
-
-func (s *Symbol) AddAddrPlus(arch *sys.Arch, t *Symbol, add int64) int64 {
-	return s.addAddrPlus(arch, t, add, objabi.R_ADDR)
-}
-
-func (s *Symbol) AddCURelativeAddrPlus(arch *sys.Arch, t *Symbol, add int64) int64 {
-	return s.addAddrPlus(arch, t, add, objabi.R_ADDRCUOFF)
-}
-
-func (s *Symbol) AddPCRelPlus(arch *sys.Arch, t *Symbol, add int64) int64 {
-	if s.Type == 0 {
-		s.Type = SDATA
-	}
-	s.Attr |= AttrReachable
-	i := s.Size
-	s.Size += 4
-	s.Grow(s.Size)
-	r := s.AddRel()
-	r.Sym = t
-	r.Off = int32(i)
-	r.Add = add
-	r.Type = objabi.R_PCREL
-	r.Siz = 4
-	if arch.Family == sys.S390X || arch.Family == sys.PPC64 {
-		r.InitExt()
-	}
-	if arch.Family == sys.S390X {
-		r.Variant = RV_390_DBL
-	}
-	return i + int64(r.Siz)
-}
-
-func (s *Symbol) AddAddr(arch *sys.Arch, t *Symbol) int64 {
-	return s.AddAddrPlus(arch, t, 0)
-}
-
-func (s *Symbol) SetAddrPlus(arch *sys.Arch, off int64, t *Symbol, add int64) int64 {
-	if s.Type == 0 {
-		s.Type = SDATA
-	}
-	s.Attr |= AttrReachable
-	if off+int64(arch.PtrSize) > s.Size {
-		s.Size = off + int64(arch.PtrSize)
-		s.Grow(s.Size)
-	}
-
-	r := s.AddRel()
-	r.Sym = t
-	r.Off = int32(off)
-	r.Siz = uint8(arch.PtrSize)
-	r.Type = objabi.R_ADDR
-	r.Add = add
-	return off + int64(r.Siz)
-}
-
-func (s *Symbol) SetAddr(arch *sys.Arch, off int64, t *Symbol) int64 {
-	return s.SetAddrPlus(arch, off, t, 0)
-}
-
-func (s *Symbol) AddSize(arch *sys.Arch, t *Symbol) int64 {
-	if s.Type == 0 {
-		s.Type = SDATA
-	}
-	s.Attr |= AttrReachable
-	i := s.Size
-	s.Size += int64(arch.PtrSize)
-	s.Grow(s.Size)
-	r := s.AddRel()
-	r.Sym = t
-	r.Off = int32(i)
-	r.Siz = uint8(arch.PtrSize)
-	r.Type = objabi.R_SIZE
-	return i + int64(r.Siz)
-}
-
-func (s *Symbol) AddAddrPlus4(t *Symbol, add int64) int64 {
-	if s.Type == 0 {
-		s.Type = SDATA
-	}
-	s.Attr |= AttrReachable
-	i := s.Size
-	s.Size += 4
-	s.Grow(s.Size)
-	r := s.AddRel()
-	r.Sym = t
-	r.Off = int32(i)
-	r.Siz = 4
-	r.Type = objabi.R_ADDR
-	r.Add = add
-	return i + int64(r.Siz)
-}
-
-func (s *Symbol) AddRel() *Reloc {
-	s.R = append(s.R, Reloc{})
-	return &s.R[len(s.R)-1]
-}
-
-func (s *Symbol) AddUintXX(arch *sys.Arch, v uint64, wid int) int64 {
-	off := s.Size
-	s.setUintXX(arch, off, v, int64(wid))
-	return off
-}
-
-func (s *Symbol) setUintXX(arch *sys.Arch, off int64, v uint64, wid int64) int64 {
-	if s.Type == 0 {
-		s.Type = SDATA
-	}
-	s.Attr |= AttrReachable
-	if s.Size < off+wid {
-		s.Size = off + wid
-		s.Grow(s.Size)
-	}
-
-	switch wid {
-	case 1:
-		s.P[off] = uint8(v)
-	case 2:
-		arch.ByteOrder.PutUint16(s.P[off:], uint16(v))
-	case 4:
-		arch.ByteOrder.PutUint32(s.P[off:], uint32(v))
-	case 8:
-		arch.ByteOrder.PutUint64(s.P[off:], v)
-	}
-
-	return off + wid
-}
-
-func (s *Symbol) makeAuxInfo() {
-	if s.auxinfo == nil {
-		s.auxinfo = &AuxSymbol{extname: s.Name, plt: -1, got: -1}
-	}
-}
-
-func (s *Symbol) Extname() string {
-	if s.auxinfo == nil {
-		return s.Name
-	}
-	return s.auxinfo.extname
-}
-
-func (s *Symbol) SetExtname(n string) {
-	if s.auxinfo == nil {
-		if s.Name == n {
-			return
-		}
-		s.makeAuxInfo()
-	}
-	s.auxinfo.extname = n
-}
-
-func (s *Symbol) Dynimplib() string {
-	if s.auxinfo == nil {
-		return ""
-	}
-	return s.auxinfo.dynimplib
-}
-
-func (s *Symbol) Dynimpvers() string {
-	if s.auxinfo == nil {
-		return ""
-	}
-	return s.auxinfo.dynimpvers
-}
-
-func (s *Symbol) SetDynimplib(lib string) {
-	if s.auxinfo == nil {
-		s.makeAuxInfo()
-	}
-	s.auxinfo.dynimplib = lib
-}
-
-func (s *Symbol) SetDynimpvers(vers string) {
-	if s.auxinfo == nil {
-		s.makeAuxInfo()
-	}
-	s.auxinfo.dynimpvers = vers
-}
-
-func (s *Symbol) ResetDyninfo() {
-	if s.auxinfo != nil {
-		s.auxinfo.dynimplib = ""
-		s.auxinfo.dynimpvers = ""
-	}
-}
-
-func (s *Symbol) Localentry() uint8 {
-	if s.auxinfo == nil {
-		return 0
-	}
-	return s.auxinfo.localentry
-}
-
-func (s *Symbol) SetLocalentry(val uint8) {
-	if s.auxinfo == nil {
-		if val != 0 {
-			return
-		}
-		s.makeAuxInfo()
-	}
-	s.auxinfo.localentry = val
-}
-
-func (s *Symbol) Plt() int32 {
-	if s.auxinfo == nil {
-		return -1
-	}
-	return s.auxinfo.plt
-}
-
-func (s *Symbol) SetPlt(val int32) {
-	if s.auxinfo == nil {
-		if val == -1 {
-			return
-		}
-		s.makeAuxInfo()
-	}
-	s.auxinfo.plt = val
-}
-
-func (s *Symbol) Got() int32 {
-	if s.auxinfo == nil {
-		return -1
-	}
-	return s.auxinfo.got
-}
-
-func (s *Symbol) SetGot(val int32) {
-	if s.auxinfo == nil {
-		if val == -1 {
-			return
-		}
-		s.makeAuxInfo()
-	}
-	s.auxinfo.got = val
-}
-
-func (s *Symbol) ElfType() elf.SymType {
-	if s.auxinfo == nil {
-		return elf.STT_NOTYPE
-	}
-	return s.auxinfo.elftype
-}
-
-func (s *Symbol) SetElfType(val elf.SymType) {
-	if s.auxinfo == nil {
-		if val == elf.STT_NOTYPE {
-			return
-		}
-		s.makeAuxInfo()
-	}
-	s.auxinfo.elftype = val
-}
-
-// SortSub sorts a linked-list (by Sub) of *Symbol by Value.
-// Used for sub-symbols when loading host objects (see e.g. ldelf.go).
-func SortSub(l *Symbol) *Symbol {
-	if l == nil || l.Sub == nil {
-		return l
-	}
-
-	l1 := l
-	l2 := l
-	for {
-		l2 = l2.Sub
-		if l2 == nil {
-			break
-		}
-		l2 = l2.Sub
-		if l2 == nil {
-			break
-		}
-		l1 = l1.Sub
-	}
-
-	l2 = l1.Sub
-	l1.Sub = nil
-	l1 = SortSub(l)
-	l2 = SortSub(l2)
-
-	/* set up lead element */
-	if l1.Value < l2.Value {
-		l = l1
-		l1 = l1.Sub
-	} else {
-		l = l2
-		l2 = l2.Sub
-	}
-
-	le := l
-
-	for {
-		if l1 == nil {
-			for l2 != nil {
-				le.Sub = l2
-				le = l2
-				l2 = l2.Sub
-			}
-
-			le.Sub = nil
-			break
-		}
-
-		if l2 == nil {
-			for l1 != nil {
-				le.Sub = l1
-				le = l1
-				l1 = l1.Sub
-			}
-
-			break
-		}
-
-		if l1.Value < l2.Value {
-			le.Sub = l1
-			le = l1
-			l1 = l1.Sub
-		} else {
-			le.Sub = l2
-			le = l2
-			l2 = l2.Sub
-		}
-	}
-
-	le.Sub = nil
-	return l
-}
-
-type FuncInfo struct {
-	Args        int32
-	Locals      int32
-	Pcsp        Pcdata
-	Pcfile      Pcdata
-	Pcline      Pcdata
-	Pcinline    Pcdata
-	Pcdata      []Pcdata
-	Funcdata    []*Symbol
-	Funcdataoff []int64
-	File        []*Symbol
-	InlTree     []InlinedCall
-}
-
-// InlinedCall is a node in a local inlining tree (FuncInfo.InlTree).
-type InlinedCall struct {
-	Parent   int32   // index of parent in InlTree
-	File     *Symbol // file of the inlined call
-	Line     int32   // line number of the inlined call
-	Func     string  // name of the function that was inlined
-	ParentPC int32   // PC of the instruction just before the inlined body (offset from function start)
-}
-
-type Pcdata struct {
-	P []byte
-}
diff --git a/src/cmd/oldlink/internal/sym/symbols.go b/src/cmd/oldlink/internal/sym/symbols.go
deleted file mode 100644
index 9dd0620..0000000
--- a/src/cmd/oldlink/internal/sym/symbols.go
+++ /dev/null
@@ -1,135 +0,0 @@
-// Derived from Inferno utils/6l/l.h and related files.
-// https://bitbucket.org/inferno-os/inferno-os/src/master/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 sym
-
-type Symbols struct {
-	symbolBatch []Symbol
-
-	// Symbol lookup based on name and indexed by version.
-	hash []map[string]*Symbol
-
-	Allsym []*Symbol
-}
-
-func NewSymbols() *Symbols {
-	hash := make([]map[string]*Symbol, SymVerStatic)
-	// Preallocate about 2mb for hash of non static symbols
-	hash[0] = make(map[string]*Symbol, 100000)
-	// And another 1mb for internal ABI text symbols.
-	hash[SymVerABIInternal] = make(map[string]*Symbol, 50000)
-	return &Symbols{
-		hash:   hash,
-		Allsym: make([]*Symbol, 0, 100000),
-	}
-}
-
-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.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)
-	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]
-}
-
-// Add an existing symbol to the symbol table.
-func (syms *Symbols) Add(s *Symbol) {
-	name := s.Name
-	v := int(s.Version)
-	m := syms.hash[v]
-	if _, ok := m[name]; ok {
-		panic(name + " already added")
-	}
-	m[name] = s
-}
-
-// Allocate a new version (i.e. symbol namespace).
-func (syms *Symbols) IncVersion() int {
-	syms.hash = append(syms.hash, make(map[string]*Symbol))
-	return len(syms.hash) - 1
-}
-
-// Rename renames a symbol.
-func (syms *Symbols) Rename(old, new string, v int, reachparent map[*Symbol]*Symbol) {
-	s := syms.hash[v][old]
-	oldExtName := s.Extname()
-	s.Name = new
-	if oldExtName == old {
-		s.SetExtname(new)
-	}
-	delete(syms.hash[v], old)
-
-	dup := syms.hash[v][new]
-	if dup == nil {
-		syms.hash[v][new] = s
-	} else {
-		if s.Type == 0 {
-			dup.Attr |= s.Attr
-			if s.Attr.Reachable() && reachparent != nil {
-				reachparent[dup] = reachparent[s]
-			}
-			*s = *dup
-		} else if dup.Type == 0 {
-			s.Attr |= dup.Attr
-			if dup.Attr.Reachable() && reachparent != nil {
-				reachparent[s] = reachparent[dup]
-			}
-			*dup = *s
-			syms.hash[v][new] = s
-		}
-	}
-}
diff --git a/src/cmd/oldlink/internal/sym/symkind.go b/src/cmd/oldlink/internal/sym/symkind.go
deleted file mode 100644
index 3a1cad9..0000000
--- a/src/cmd/oldlink/internal/sym/symkind.go
+++ /dev/null
@@ -1,168 +0,0 @@
-// Derived from Inferno utils/6l/l.h and related files.
-// https://bitbucket.org/inferno-os/inferno-os/src/master/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 sym
-
-// A SymKind describes the kind of memory represented by a symbol.
-type SymKind uint8
-
-// Defined SymKind values.
-//
-// TODO(rsc): Give idiomatic Go names.
-//go:generate stringer -type=SymKind
-const (
-	Sxxx SymKind = iota
-	STEXT
-	SELFRXSECT
-
-	// Read-only sections.
-	STYPE
-	SSTRING
-	SGOSTRING
-	SGOFUNC
-	SGCBITS
-	SRODATA
-	SFUNCTAB
-
-	SELFROSECT
-	SMACHOPLT
-
-	// Read-only sections with relocations.
-	//
-	// Types STYPE-SFUNCTAB above are written to the .rodata section by default.
-	// When linking a shared object, some conceptually "read only" types need to
-	// be written to by relocations and putting them in a section called
-	// ".rodata" interacts poorly with the system linkers. The GNU linkers
-	// support this situation by arranging for sections of the name
-	// ".data.rel.ro.XXX" to be mprotected read only by the dynamic linker after
-	// relocations have applied, so when the Go linker is creating a shared
-	// object it checks all objects of the above types and bumps any object that
-	// has a relocation to it to the corresponding type below, which are then
-	// written to sections with appropriate magic names.
-	STYPERELRO
-	SSTRINGRELRO
-	SGOSTRINGRELRO
-	SGOFUNCRELRO
-	SGCBITSRELRO
-	SRODATARELRO
-	SFUNCTABRELRO
-
-	// Part of .data.rel.ro if it exists, otherwise part of .rodata.
-	STYPELINK
-	SITABLINK
-	SSYMTAB
-	SPCLNTAB
-
-	// Writable sections.
-	SFirstWritable
-	SBUILDINFO
-	SELFSECT
-	SMACHO
-	SMACHOGOT
-	SWINDOWS
-	SELFGOT
-	SNOPTRDATA
-	SINITARR
-	SDATA
-	SXCOFFTOC
-	SBSS
-	SNOPTRBSS
-	SLIBFUZZER_EXTRA_COUNTER
-	STLSBSS
-	SXREF
-	SMACHOSYMSTR
-	SMACHOSYMTAB
-	SMACHOINDIRECTPLT
-	SMACHOINDIRECTGOT
-	SFILEPATH
-	SCONST
-	SDYNIMPORT
-	SHOSTOBJ
-	SUNDEFEXT // Undefined symbol for resolution by external linker
-
-	// Sections for debugging information
-	SDWARFSECT
-	SDWARFINFO
-	SDWARFRANGE
-	SDWARFLOC
-	SDWARFLINES
-
-	// ABI aliases (these never appear in the output)
-	SABIALIAS
-)
-
-// AbiSymKindToSymKind maps values read from object files (which are
-// of type cmd/internal/objabi.SymKind) to values of type SymKind.
-var AbiSymKindToSymKind = [...]SymKind{
-	Sxxx,
-	STEXT,
-	SRODATA,
-	SNOPTRDATA,
-	SDATA,
-	SBSS,
-	SNOPTRBSS,
-	STLSBSS,
-	SDWARFINFO,
-	SDWARFRANGE,
-	SDWARFLOC,
-	SDWARFLINES,
-	SABIALIAS,
-	SLIBFUZZER_EXTRA_COUNTER,
-}
-
-// ReadOnly are the symbol kinds that form read-only sections. In some
-// cases, if they will require relocations, they are transformed into
-// rel-ro sections using relROMap.
-var ReadOnly = []SymKind{
-	STYPE,
-	SSTRING,
-	SGOSTRING,
-	SGOFUNC,
-	SGCBITS,
-	SRODATA,
-	SFUNCTAB,
-}
-
-// RelROMap describes the transformation of read-only symbols to rel-ro
-// symbols.
-var RelROMap = map[SymKind]SymKind{
-	STYPE:     STYPERELRO,
-	SSTRING:   SSTRINGRELRO,
-	SGOSTRING: SGOSTRINGRELRO,
-	SGOFUNC:   SGOFUNCRELRO,
-	SGCBITS:   SGCBITSRELRO,
-	SRODATA:   SRODATARELRO,
-	SFUNCTAB:  SFUNCTABRELRO,
-}
-
-// IsData returns true if the type is a data type.
-func (t SymKind) IsData() bool {
-	return t == SDATA || t == SNOPTRDATA || t == SBSS || t == SNOPTRBSS
-}
diff --git a/src/cmd/oldlink/internal/sym/symkind_string.go b/src/cmd/oldlink/internal/sym/symkind_string.go
deleted file mode 100644
index 97af992..0000000
--- a/src/cmd/oldlink/internal/sym/symkind_string.go
+++ /dev/null
@@ -1,76 +0,0 @@
-// Code generated by "stringer -type=SymKind symkind.go"; DO NOT EDIT.
-
-package sym
-
-import "strconv"
-
-func _() {
-	// An "invalid array index" compiler error signifies that the constant values have changed.
-	// Re-run the stringer command to generate them again.
-	var x [1]struct{}
-	_ = x[Sxxx-0]
-	_ = x[STEXT-1]
-	_ = x[SELFRXSECT-2]
-	_ = x[STYPE-3]
-	_ = x[SSTRING-4]
-	_ = x[SGOSTRING-5]
-	_ = x[SGOFUNC-6]
-	_ = x[SGCBITS-7]
-	_ = x[SRODATA-8]
-	_ = x[SFUNCTAB-9]
-	_ = x[SELFROSECT-10]
-	_ = x[SMACHOPLT-11]
-	_ = x[STYPERELRO-12]
-	_ = x[SSTRINGRELRO-13]
-	_ = x[SGOSTRINGRELRO-14]
-	_ = x[SGOFUNCRELRO-15]
-	_ = x[SGCBITSRELRO-16]
-	_ = x[SRODATARELRO-17]
-	_ = x[SFUNCTABRELRO-18]
-	_ = x[STYPELINK-19]
-	_ = x[SITABLINK-20]
-	_ = x[SSYMTAB-21]
-	_ = x[SPCLNTAB-22]
-	_ = x[SFirstWritable-23]
-	_ = x[SBUILDINFO-24]
-	_ = x[SELFSECT-25]
-	_ = x[SMACHO-26]
-	_ = x[SMACHOGOT-27]
-	_ = x[SWINDOWS-28]
-	_ = x[SELFGOT-29]
-	_ = x[SNOPTRDATA-30]
-	_ = x[SINITARR-31]
-	_ = x[SDATA-32]
-	_ = x[SXCOFFTOC-33]
-	_ = x[SBSS-34]
-	_ = x[SNOPTRBSS-35]
-	_ = x[SLIBFUZZER_EXTRA_COUNTER-36]
-	_ = x[STLSBSS-37]
-	_ = x[SXREF-38]
-	_ = x[SMACHOSYMSTR-39]
-	_ = x[SMACHOSYMTAB-40]
-	_ = x[SMACHOINDIRECTPLT-41]
-	_ = x[SMACHOINDIRECTGOT-42]
-	_ = x[SFILEPATH-43]
-	_ = x[SCONST-44]
-	_ = x[SDYNIMPORT-45]
-	_ = x[SHOSTOBJ-46]
-	_ = x[SUNDEFEXT-47]
-	_ = x[SDWARFSECT-48]
-	_ = x[SDWARFINFO-49]
-	_ = x[SDWARFRANGE-50]
-	_ = x[SDWARFLOC-51]
-	_ = x[SDWARFLINES-52]
-	_ = x[SABIALIAS-53]
-}
-
-const _SymKind_name = "SxxxSTEXTSELFRXSECTSTYPESSTRINGSGOSTRINGSGOFUNCSGCBITSSRODATASFUNCTABSELFROSECTSMACHOPLTSTYPERELROSSTRINGRELROSGOSTRINGRELROSGOFUNCRELROSGCBITSRELROSRODATARELROSFUNCTABRELROSTYPELINKSITABLINKSSYMTABSPCLNTABSFirstWritableSBUILDINFOSELFSECTSMACHOSMACHOGOTSWINDOWSSELFGOTSNOPTRDATASINITARRSDATASXCOFFTOCSBSSSNOPTRBSSSLIBFUZZER_EXTRA_COUNTERSTLSBSSSXREFSMACHOSYMSTRSMACHOSYMTABSMACHOINDIRECTPLTSMACHOINDIRECTGOTSFILEPATHSCONSTSDYNIMPORTSHOSTOBJSUNDEFEXTSDWARFSECTSDWARFINFOSDWARFRANGESDWARFLOCSDWARFLINESSABIALIAS"
-
-var _SymKind_index = [...]uint16{0, 4, 9, 19, 24, 31, 40, 47, 54, 61, 69, 79, 88, 98, 110, 124, 136, 148, 160, 173, 182, 191, 198, 206, 220, 230, 238, 244, 253, 261, 268, 278, 286, 291, 300, 304, 313, 337, 344, 349, 361, 373, 390, 407, 416, 422, 432, 440, 449, 459, 469, 480, 489, 500, 509}
-
-func (i SymKind) String() string {
-	if i >= SymKind(len(_SymKind_index)-1) {
-		return "SymKind(" + strconv.FormatInt(int64(i), 10) + ")"
-	}
-	return _SymKind_name[_SymKind_index[i]:_SymKind_index[i+1]]
-}
diff --git a/src/cmd/oldlink/internal/wasm/asm.go b/src/cmd/oldlink/internal/wasm/asm.go
deleted file mode 100644
index 35bc7b1..0000000
--- a/src/cmd/oldlink/internal/wasm/asm.go
+++ /dev/null
@@ -1,583 +0,0 @@
-// Copyright 2018 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 wasm
-
-import (
-	"bytes"
-	"cmd/internal/objabi"
-	"cmd/oldlink/internal/ld"
-	"cmd/oldlink/internal/sym"
-	"io"
-	"regexp"
-)
-
-const (
-	I32 = 0x7F
-	I64 = 0x7E
-	F32 = 0x7D
-	F64 = 0x7C
-)
-
-const (
-	sectionCustom   = 0
-	sectionType     = 1
-	sectionImport   = 2
-	sectionFunction = 3
-	sectionTable    = 4
-	sectionMemory   = 5
-	sectionGlobal   = 6
-	sectionExport   = 7
-	sectionStart    = 8
-	sectionElement  = 9
-	sectionCode     = 10
-	sectionData     = 11
-)
-
-// funcValueOffset is the offset between the PC_F value of a function and the index of the function in WebAssembly
-const funcValueOffset = 0x1000 // TODO(neelance): make function addresses play nice with heap addresses
-
-func gentext(ctxt *ld.Link) {
-}
-
-type wasmFunc struct {
-	Name string
-	Type uint32
-	Code []byte
-}
-
-type wasmFuncType struct {
-	Params  []byte
-	Results []byte
-}
-
-var wasmFuncTypes = map[string]*wasmFuncType{
-	"_rt0_wasm_js":           {Params: []byte{}},                                         //
-	"wasm_export_run":        {Params: []byte{I32, I32}},                                 // argc, argv
-	"wasm_export_resume":     {Params: []byte{}},                                         //
-	"wasm_export_getsp":      {Results: []byte{I32}},                                     // sp
-	"wasm_pc_f_loop":         {Params: []byte{}},                                         //
-	"runtime.wasmMove":       {Params: []byte{I32, I32, I32}},                            // dst, src, len
-	"runtime.wasmZero":       {Params: []byte{I32, I32}},                                 // ptr, len
-	"runtime.wasmDiv":        {Params: []byte{I64, I64}, Results: []byte{I64}},           // x, y -> x/y
-	"runtime.wasmTruncS":     {Params: []byte{F64}, Results: []byte{I64}},                // x -> int(x)
-	"runtime.wasmTruncU":     {Params: []byte{F64}, Results: []byte{I64}},                // x -> uint(x)
-	"runtime.gcWriteBarrier": {Params: []byte{I64, I64}},                                 // ptr, val
-	"cmpbody":                {Params: []byte{I64, I64, I64, I64}, Results: []byte{I64}}, // a, alen, b, blen -> -1/0/1
-	"memeqbody":              {Params: []byte{I64, I64, I64}, Results: []byte{I64}},      // a, b, len -> 0/1
-	"memcmp":                 {Params: []byte{I32, I32, I32}, Results: []byte{I32}},      // a, b, len -> <0/0/>0
-	"memchr":                 {Params: []byte{I32, I32, I32}, Results: []byte{I32}},      // s, c, len -> index
-}
-
-func assignAddress(ctxt *ld.Link, sect *sym.Section, n int, s *sym.Symbol, va uint64, isTramp bool) (*sym.Section, int, uint64) {
-	// WebAssembly functions do not live in the same address space as the linear memory.
-	// Instead, WebAssembly automatically assigns indices. Imported functions (section "import")
-	// have indices 0 to n. They are followed by native functions (sections "function" and "code")
-	// with indices n+1 and following.
-	//
-	// The following rules describe how wasm handles function indices and addresses:
-	//   PC_F = funcValueOffset + WebAssembly function index (not including the imports)
-	//   s.Value = PC = PC_F<<16 + PC_B
-	//
-	// The funcValueOffset is necessary to avoid conflicts with expectations
-	// that the Go runtime has about function addresses.
-	// The field "s.Value" corresponds to the concept of PC at runtime.
-	// However, there is no PC register, only PC_F and PC_B. PC_F denotes the function,
-	// PC_B the resume point inside of that function. The entry of the function has PC_B = 0.
-	s.Sect = sect
-	s.Value = int64(funcValueOffset+va/ld.MINFUNC) << 16 // va starts at zero
-	va += uint64(ld.MINFUNC)
-	return sect, n, va
-}
-
-func asmb(ctxt *ld.Link) {} // dummy
-
-// asmb writes the final WebAssembly module binary.
-// Spec: https://webassembly.github.io/spec/core/binary/modules.html
-func asmb2(ctxt *ld.Link) {
-	types := []*wasmFuncType{
-		// For normal Go functions, the single parameter is PC_B,
-		// the return value is
-		// 0 if the function returned normally or
-		// 1 if the stack needs to be unwound.
-		{Params: []byte{I32}, Results: []byte{I32}},
-	}
-
-	// collect host imports (functions that get imported from the WebAssembly host, usually JavaScript)
-	hostImports := []*wasmFunc{
-		{
-			Name: "debug",
-			Type: lookupType(&wasmFuncType{Params: []byte{I32}}, &types),
-		},
-	}
-	hostImportMap := make(map[*sym.Symbol]int64)
-	for _, fn := range ctxt.Textp {
-		for _, r := range fn.R {
-			if r.Type == objabi.R_WASMIMPORT {
-				hostImportMap[r.Sym] = int64(len(hostImports))
-				hostImports = append(hostImports, &wasmFunc{
-					Name: r.Sym.Name,
-					Type: lookupType(&wasmFuncType{Params: []byte{I32}}, &types),
-				})
-			}
-		}
-	}
-
-	// collect functions with WebAssembly body
-	var buildid []byte
-	fns := make([]*wasmFunc, len(ctxt.Textp))
-	for i, fn := range ctxt.Textp {
-		wfn := new(bytes.Buffer)
-		if fn.Name == "go.buildid" {
-			writeUleb128(wfn, 0) // number of sets of locals
-			writeI32Const(wfn, 0)
-			wfn.WriteByte(0x0b) // end
-			buildid = fn.P
-		} else {
-			// Relocations have variable length, handle them here.
-			off := int32(0)
-			for _, r := range fn.R {
-				wfn.Write(fn.P[off:r.Off])
-				off = r.Off
-				switch r.Type {
-				case objabi.R_ADDR:
-					writeSleb128(wfn, r.Sym.Value+r.Add)
-				case objabi.R_CALL:
-					writeSleb128(wfn, int64(len(hostImports))+r.Sym.Value>>16-funcValueOffset)
-				case objabi.R_WASMIMPORT:
-					writeSleb128(wfn, hostImportMap[r.Sym])
-				default:
-					ld.Errorf(fn, "bad reloc type %d (%s)", r.Type, sym.RelocName(ctxt.Arch, r.Type))
-					continue
-				}
-			}
-			wfn.Write(fn.P[off:])
-		}
-
-		typ := uint32(0)
-		if sig, ok := wasmFuncTypes[fn.Name]; ok {
-			typ = lookupType(sig, &types)
-		}
-
-		name := nameRegexp.ReplaceAllString(fn.Name, "_")
-		fns[i] = &wasmFunc{Name: name, Type: typ, Code: wfn.Bytes()}
-	}
-
-	ctxt.Out.Write([]byte{0x00, 0x61, 0x73, 0x6d}) // magic
-	ctxt.Out.Write([]byte{0x01, 0x00, 0x00, 0x00}) // version
-
-	// Add any buildid early in the binary:
-	if len(buildid) != 0 {
-		writeBuildID(ctxt, buildid)
-	}
-
-	writeTypeSec(ctxt, types)
-	writeImportSec(ctxt, hostImports)
-	writeFunctionSec(ctxt, fns)
-	writeTableSec(ctxt, fns)
-	writeMemorySec(ctxt)
-	writeGlobalSec(ctxt)
-	writeExportSec(ctxt, len(hostImports))
-	writeElementSec(ctxt, uint64(len(hostImports)), uint64(len(fns)))
-	writeCodeSec(ctxt, fns)
-	writeDataSec(ctxt)
-	writeProducerSec(ctxt)
-	if !*ld.FlagS {
-		writeNameSec(ctxt, len(hostImports), fns)
-	}
-
-	ctxt.Out.Flush()
-}
-
-func lookupType(sig *wasmFuncType, types *[]*wasmFuncType) uint32 {
-	for i, t := range *types {
-		if bytes.Equal(sig.Params, t.Params) && bytes.Equal(sig.Results, t.Results) {
-			return uint32(i)
-		}
-	}
-	*types = append(*types, sig)
-	return uint32(len(*types) - 1)
-}
-
-func writeSecHeader(ctxt *ld.Link, id uint8) int64 {
-	ctxt.Out.WriteByte(id)
-	sizeOffset := ctxt.Out.Offset()
-	ctxt.Out.Write(make([]byte, 5)) // placeholder for length
-	return sizeOffset
-}
-
-func writeSecSize(ctxt *ld.Link, sizeOffset int64) {
-	endOffset := ctxt.Out.Offset()
-	ctxt.Out.SeekSet(sizeOffset)
-	writeUleb128FixedLength(ctxt.Out, uint64(endOffset-sizeOffset-5), 5)
-	ctxt.Out.SeekSet(endOffset)
-}
-
-func writeBuildID(ctxt *ld.Link, buildid []byte) {
-	sizeOffset := writeSecHeader(ctxt, sectionCustom)
-	writeName(ctxt.Out, "go.buildid")
-	ctxt.Out.Write(buildid)
-	writeSecSize(ctxt, sizeOffset)
-}
-
-// writeTypeSec writes the section that declares all function types
-// so they can be referenced by index.
-func writeTypeSec(ctxt *ld.Link, types []*wasmFuncType) {
-	sizeOffset := writeSecHeader(ctxt, sectionType)
-
-	writeUleb128(ctxt.Out, uint64(len(types)))
-
-	for _, t := range types {
-		ctxt.Out.WriteByte(0x60) // functype
-		writeUleb128(ctxt.Out, uint64(len(t.Params)))
-		for _, v := range t.Params {
-			ctxt.Out.WriteByte(byte(v))
-		}
-		writeUleb128(ctxt.Out, uint64(len(t.Results)))
-		for _, v := range t.Results {
-			ctxt.Out.WriteByte(byte(v))
-		}
-	}
-
-	writeSecSize(ctxt, sizeOffset)
-}
-
-// writeImportSec writes the section that lists the functions that get
-// imported from the WebAssembly host, usually JavaScript.
-func writeImportSec(ctxt *ld.Link, hostImports []*wasmFunc) {
-	sizeOffset := writeSecHeader(ctxt, sectionImport)
-
-	writeUleb128(ctxt.Out, uint64(len(hostImports))) // number of imports
-	for _, fn := range hostImports {
-		writeName(ctxt.Out, "go") // provided by the import object in wasm_exec.js
-		writeName(ctxt.Out, fn.Name)
-		ctxt.Out.WriteByte(0x00) // func import
-		writeUleb128(ctxt.Out, uint64(fn.Type))
-	}
-
-	writeSecSize(ctxt, sizeOffset)
-}
-
-// writeFunctionSec writes the section that declares the types of functions.
-// The bodies of these functions will later be provided in the "code" section.
-func writeFunctionSec(ctxt *ld.Link, fns []*wasmFunc) {
-	sizeOffset := writeSecHeader(ctxt, sectionFunction)
-
-	writeUleb128(ctxt.Out, uint64(len(fns)))
-	for _, fn := range fns {
-		writeUleb128(ctxt.Out, uint64(fn.Type))
-	}
-
-	writeSecSize(ctxt, sizeOffset)
-}
-
-// writeTableSec writes the section that declares tables. Currently there is only a single table
-// that is used by the CallIndirect operation to dynamically call any function.
-// The contents of the table get initialized by the "element" section.
-func writeTableSec(ctxt *ld.Link, fns []*wasmFunc) {
-	sizeOffset := writeSecHeader(ctxt, sectionTable)
-
-	numElements := uint64(funcValueOffset + len(fns))
-	writeUleb128(ctxt.Out, 1)           // number of tables
-	ctxt.Out.WriteByte(0x70)            // type: anyfunc
-	ctxt.Out.WriteByte(0x00)            // no max
-	writeUleb128(ctxt.Out, numElements) // min
-
-	writeSecSize(ctxt, sizeOffset)
-}
-
-// writeMemorySec writes the section that declares linear memories. Currently one linear memory is being used.
-// Linear memory always starts at address zero. More memory can be requested with the GrowMemory instruction.
-func writeMemorySec(ctxt *ld.Link) {
-	sizeOffset := writeSecHeader(ctxt, sectionMemory)
-
-	dataSection := ctxt.Syms.Lookup("runtime.data", 0).Sect
-	dataEnd := dataSection.Vaddr + dataSection.Length
-	var initialSize = dataEnd + 16<<20 // 16MB, enough for runtime init without growing
-
-	const wasmPageSize = 64 << 10 // 64KB
-
-	writeUleb128(ctxt.Out, 1)                        // number of memories
-	ctxt.Out.WriteByte(0x00)                         // no maximum memory size
-	writeUleb128(ctxt.Out, initialSize/wasmPageSize) // minimum (initial) memory size
-
-	writeSecSize(ctxt, sizeOffset)
-}
-
-// writeGlobalSec writes the section that declares global variables.
-func writeGlobalSec(ctxt *ld.Link) {
-	sizeOffset := writeSecHeader(ctxt, sectionGlobal)
-
-	globalRegs := []byte{
-		I32, // 0: SP
-		I64, // 1: CTXT
-		I64, // 2: g
-		I64, // 3: RET0
-		I64, // 4: RET1
-		I64, // 5: RET2
-		I64, // 6: RET3
-		I32, // 7: PAUSE
-	}
-
-	writeUleb128(ctxt.Out, uint64(len(globalRegs))) // number of globals
-
-	for _, typ := range globalRegs {
-		ctxt.Out.WriteByte(typ)
-		ctxt.Out.WriteByte(0x01) // var
-		switch typ {
-		case I32:
-			writeI32Const(ctxt.Out, 0)
-		case I64:
-			writeI64Const(ctxt.Out, 0)
-		}
-		ctxt.Out.WriteByte(0x0b) // end
-	}
-
-	writeSecSize(ctxt, sizeOffset)
-}
-
-// writeExportSec writes the section that declares exports.
-// Exports can be accessed by the WebAssembly host, usually JavaScript.
-// The wasm_export_* functions and the linear memory get exported.
-func writeExportSec(ctxt *ld.Link, lenHostImports int) {
-	sizeOffset := writeSecHeader(ctxt, sectionExport)
-
-	writeUleb128(ctxt.Out, 4) // number of exports
-
-	for _, name := range []string{"run", "resume", "getsp"} {
-		idx := uint32(lenHostImports) + uint32(ctxt.Syms.ROLookup("wasm_export_"+name, 0).Value>>16) - funcValueOffset
-		writeName(ctxt.Out, name)           // inst.exports.run/resume/getsp in wasm_exec.js
-		ctxt.Out.WriteByte(0x00)            // func export
-		writeUleb128(ctxt.Out, uint64(idx)) // funcidx
-	}
-
-	writeName(ctxt.Out, "mem") // inst.exports.mem in wasm_exec.js
-	ctxt.Out.WriteByte(0x02)   // mem export
-	writeUleb128(ctxt.Out, 0)  // memidx
-
-	writeSecSize(ctxt, sizeOffset)
-}
-
-// writeElementSec writes the section that initializes the tables declared by the "table" section.
-// The table for CallIndirect gets initialized in a very simple way so that each table index (PC_F value)
-// maps linearly to the function index (numImports + PC_F).
-func writeElementSec(ctxt *ld.Link, numImports, numFns uint64) {
-	sizeOffset := writeSecHeader(ctxt, sectionElement)
-
-	writeUleb128(ctxt.Out, 1) // number of element segments
-
-	writeUleb128(ctxt.Out, 0) // tableidx
-	writeI32Const(ctxt.Out, funcValueOffset)
-	ctxt.Out.WriteByte(0x0b) // end
-
-	writeUleb128(ctxt.Out, numFns) // number of entries
-	for i := uint64(0); i < numFns; i++ {
-		writeUleb128(ctxt.Out, numImports+i)
-	}
-
-	writeSecSize(ctxt, sizeOffset)
-}
-
-// writeElementSec writes the section that provides the function bodies for the functions
-// declared by the "func" section.
-func writeCodeSec(ctxt *ld.Link, fns []*wasmFunc) {
-	sizeOffset := writeSecHeader(ctxt, sectionCode)
-
-	writeUleb128(ctxt.Out, uint64(len(fns))) // number of code entries
-	for _, fn := range fns {
-		writeUleb128(ctxt.Out, uint64(len(fn.Code)))
-		ctxt.Out.Write(fn.Code)
-	}
-
-	writeSecSize(ctxt, sizeOffset)
-}
-
-// writeDataSec writes the section that provides data that will be used to initialize the linear memory.
-func writeDataSec(ctxt *ld.Link) {
-	sizeOffset := writeSecHeader(ctxt, sectionData)
-
-	sections := []*sym.Section{
-		ctxt.Syms.Lookup("runtime.rodata", 0).Sect,
-		ctxt.Syms.Lookup("runtime.typelink", 0).Sect,
-		ctxt.Syms.Lookup("runtime.itablink", 0).Sect,
-		ctxt.Syms.Lookup("runtime.symtab", 0).Sect,
-		ctxt.Syms.Lookup("runtime.pclntab", 0).Sect,
-		ctxt.Syms.Lookup("runtime.noptrdata", 0).Sect,
-		ctxt.Syms.Lookup("runtime.data", 0).Sect,
-	}
-
-	type dataSegment struct {
-		offset int32
-		data   []byte
-	}
-
-	// Omit blocks of zeroes and instead emit data segments with offsets skipping the zeroes.
-	// This reduces the size of the WebAssembly binary. We use 8 bytes as an estimate for the
-	// overhead of adding a new segment (same as wasm-opt's memory-packing optimization uses).
-	const segmentOverhead = 8
-
-	// Generate at most this many segments. A higher number of segments gets rejected by some WebAssembly runtimes.
-	const maxNumSegments = 100000
-
-	var segments []*dataSegment
-	for secIndex, sec := range sections {
-		data := ld.DatblkBytes(ctxt, int64(sec.Vaddr), int64(sec.Length))
-		offset := int32(sec.Vaddr)
-
-		// skip leading zeroes
-		for len(data) > 0 && data[0] == 0 {
-			data = data[1:]
-			offset++
-		}
-
-		for len(data) > 0 {
-			dataLen := int32(len(data))
-			var segmentEnd, zeroEnd int32
-			if len(segments)+(len(sections)-secIndex) == maxNumSegments {
-				segmentEnd = dataLen
-				zeroEnd = dataLen
-			} else {
-				for {
-					// look for beginning of zeroes
-					for segmentEnd < dataLen && data[segmentEnd] != 0 {
-						segmentEnd++
-					}
-					// look for end of zeroes
-					zeroEnd = segmentEnd
-					for zeroEnd < dataLen && data[zeroEnd] == 0 {
-						zeroEnd++
-					}
-					// emit segment if omitting zeroes reduces the output size
-					if zeroEnd-segmentEnd >= segmentOverhead || zeroEnd == dataLen {
-						break
-					}
-					segmentEnd = zeroEnd
-				}
-			}
-
-			segments = append(segments, &dataSegment{
-				offset: offset,
-				data:   data[:segmentEnd],
-			})
-			data = data[zeroEnd:]
-			offset += zeroEnd
-		}
-	}
-
-	writeUleb128(ctxt.Out, uint64(len(segments))) // number of data entries
-	for _, seg := range segments {
-		writeUleb128(ctxt.Out, 0) // memidx
-		writeI32Const(ctxt.Out, seg.offset)
-		ctxt.Out.WriteByte(0x0b) // end
-		writeUleb128(ctxt.Out, uint64(len(seg.data)))
-		ctxt.Out.Write(seg.data)
-	}
-
-	writeSecSize(ctxt, sizeOffset)
-}
-
-// writeProducerSec writes an optional section that reports the source language and compiler version.
-func writeProducerSec(ctxt *ld.Link) {
-	sizeOffset := writeSecHeader(ctxt, sectionCustom)
-	writeName(ctxt.Out, "producers")
-
-	writeUleb128(ctxt.Out, 2) // number of fields
-
-	writeName(ctxt.Out, "language")     // field name
-	writeUleb128(ctxt.Out, 1)           // number of values
-	writeName(ctxt.Out, "Go")           // value: name
-	writeName(ctxt.Out, objabi.Version) // value: version
-
-	writeName(ctxt.Out, "processed-by")   // field name
-	writeUleb128(ctxt.Out, 1)             // number of values
-	writeName(ctxt.Out, "Go cmd/compile") // value: name
-	writeName(ctxt.Out, objabi.Version)   // value: version
-
-	writeSecSize(ctxt, sizeOffset)
-}
-
-var nameRegexp = regexp.MustCompile(`[^\w\.]`)
-
-// writeNameSec writes an optional section that assigns names to the functions declared by the "func" section.
-// The names are only used by WebAssembly stack traces, debuggers and decompilers.
-// TODO(neelance): add symbol table of DATA symbols
-func writeNameSec(ctxt *ld.Link, firstFnIndex int, fns []*wasmFunc) {
-	sizeOffset := writeSecHeader(ctxt, sectionCustom)
-	writeName(ctxt.Out, "name")
-
-	sizeOffset2 := writeSecHeader(ctxt, 0x01) // function names
-	writeUleb128(ctxt.Out, uint64(len(fns)))
-	for i, fn := range fns {
-		writeUleb128(ctxt.Out, uint64(firstFnIndex+i))
-		writeName(ctxt.Out, fn.Name)
-	}
-	writeSecSize(ctxt, sizeOffset2)
-
-	writeSecSize(ctxt, sizeOffset)
-}
-
-type nameWriter interface {
-	io.ByteWriter
-	io.Writer
-}
-
-func writeI32Const(w io.ByteWriter, v int32) {
-	w.WriteByte(0x41) // i32.const
-	writeSleb128(w, int64(v))
-}
-
-func writeI64Const(w io.ByteWriter, v int64) {
-	w.WriteByte(0x42) // i64.const
-	writeSleb128(w, v)
-}
-
-func writeName(w nameWriter, name string) {
-	writeUleb128(w, uint64(len(name)))
-	w.Write([]byte(name))
-}
-
-func writeUleb128(w io.ByteWriter, v uint64) {
-	if v < 128 {
-		w.WriteByte(uint8(v))
-		return
-	}
-	more := true
-	for more {
-		c := uint8(v & 0x7f)
-		v >>= 7
-		more = v != 0
-		if more {
-			c |= 0x80
-		}
-		w.WriteByte(c)
-	}
-}
-
-func writeUleb128FixedLength(w io.ByteWriter, v uint64, length int) {
-	for i := 0; i < length; i++ {
-		c := uint8(v & 0x7f)
-		v >>= 7
-		if i < length-1 {
-			c |= 0x80
-		}
-		w.WriteByte(c)
-	}
-	if v != 0 {
-		panic("writeUleb128FixedLength: length too small")
-	}
-}
-
-func writeSleb128(w io.ByteWriter, v int64) {
-	more := true
-	for more {
-		c := uint8(v & 0x7f)
-		s := uint8(v & 0x40)
-		v >>= 7
-		more = !((v == 0 && s == 0) || (v == -1 && s != 0))
-		if more {
-			c |= 0x80
-		}
-		w.WriteByte(c)
-	}
-}
diff --git a/src/cmd/oldlink/internal/wasm/obj.go b/src/cmd/oldlink/internal/wasm/obj.go
deleted file mode 100644
index fdc9fb7..0000000
--- a/src/cmd/oldlink/internal/wasm/obj.go
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright 2018 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 wasm
-
-import (
-	"cmd/internal/sys"
-	"cmd/oldlink/internal/ld"
-)
-
-func Init() (*sys.Arch, ld.Arch) {
-	theArch := ld.Arch{
-		Funcalign: 16,
-		Maxalign:  32,
-		Minalign:  1,
-
-		Archinit:      archinit,
-		AssignAddress: assignAddress,
-		Asmb:          asmb,
-		Asmb2:         asmb2,
-		Gentext:       gentext,
-	}
-
-	return sys.ArchWasm, theArch
-}
-
-func archinit(ctxt *ld.Link) {
-	if *ld.FlagRound == -1 {
-		*ld.FlagRound = 4096
-	}
-	if *ld.FlagTextAddr == -1 {
-		*ld.FlagTextAddr = 0
-	}
-}
diff --git a/src/cmd/oldlink/internal/x86/asm.go b/src/cmd/oldlink/internal/x86/asm.go
deleted file mode 100644
index df8a236..0000000
--- a/src/cmd/oldlink/internal/x86/asm.go
+++ /dev/null
@@ -1,699 +0,0 @@
-// Inferno utils/8l/asm.c
-// https://bitbucket.org/inferno-os/inferno-os/src/master/utils/8l/asm.c
-//
-//	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 x86
-
-import (
-	"cmd/internal/objabi"
-	"cmd/internal/sys"
-	"cmd/oldlink/internal/ld"
-	"cmd/oldlink/internal/sym"
-	"debug/elf"
-	"log"
-)
-
-// Append 4 bytes to s and create a R_CALL relocation targeting t to fill them in.
-func addcall(ctxt *ld.Link, s *sym.Symbol, t *sym.Symbol) {
-	s.Attr |= sym.AttrReachable
-	i := s.Size
-	s.Size += 4
-	s.Grow(s.Size)
-	r := s.AddRel()
-	r.Sym = t
-	r.Off = int32(i)
-	r.Type = objabi.R_CALL
-	r.Siz = 4
-}
-
-func gentext(ctxt *ld.Link) {
-	if ctxt.DynlinkingGo() {
-		// We need get_pc_thunk.
-	} else {
-		switch ctxt.BuildMode {
-		case ld.BuildModeCArchive:
-			if !ctxt.IsELF {
-				return
-			}
-		case ld.BuildModePIE, ld.BuildModeCShared, ld.BuildModePlugin:
-			// We need get_pc_thunk.
-		default:
-			return
-		}
-	}
-
-	// Generate little thunks that load the PC of the next instruction into a register.
-	thunks := make([]*sym.Symbol, 0, 7+len(ctxt.Textp))
-	for _, r := range [...]struct {
-		name string
-		num  uint8
-	}{
-		{"ax", 0},
-		{"cx", 1},
-		{"dx", 2},
-		{"bx", 3},
-		// sp
-		{"bp", 5},
-		{"si", 6},
-		{"di", 7},
-	} {
-		thunkfunc := ctxt.Syms.Lookup("__x86.get_pc_thunk."+r.name, 0)
-		thunkfunc.Type = sym.STEXT
-		thunkfunc.Attr |= sym.AttrLocal
-		thunkfunc.Attr |= sym.AttrReachable //TODO: remove?
-		o := func(op ...uint8) {
-			for _, op1 := range op {
-				thunkfunc.AddUint8(op1)
-			}
-		}
-		// 8b 04 24	mov    (%esp),%eax
-		// Destination register is in bits 3-5 of the middle byte, so add that in.
-		o(0x8b, 0x04+r.num<<3, 0x24)
-		// c3		ret
-		o(0xc3)
-
-		thunks = append(thunks, thunkfunc)
-	}
-	ctxt.Textp = append(thunks, ctxt.Textp...) // keep Textp in dependency order
-
-	addmoduledata := ctxt.Syms.Lookup("runtime.addmoduledata", 0)
-	if addmoduledata.Type == sym.STEXT && ctxt.BuildMode != ld.BuildModePlugin {
-		// we're linking a module containing the runtime -> no need for
-		// an init function
-		return
-	}
-
-	addmoduledata.Attr |= sym.AttrReachable
-
-	initfunc := ctxt.Syms.Lookup("go.link.addmoduledata", 0)
-	initfunc.Type = sym.STEXT
-	initfunc.Attr |= sym.AttrLocal
-	initfunc.Attr |= sym.AttrReachable
-	o := func(op ...uint8) {
-		for _, op1 := range op {
-			initfunc.AddUint8(op1)
-		}
-	}
-
-	// go.link.addmoduledata:
-	//      53                      push %ebx
-	//      e8 00 00 00 00          call __x86.get_pc_thunk.cx + R_CALL __x86.get_pc_thunk.cx
-	//      8d 81 00 00 00 00       lea 0x0(%ecx), %eax + R_PCREL ctxt.Moduledata
-	//      8d 99 00 00 00 00       lea 0x0(%ecx), %ebx + R_GOTPC _GLOBAL_OFFSET_TABLE_
-	//      e8 00 00 00 00          call runtime.addmoduledata@plt + R_CALL runtime.addmoduledata
-	//      5b                      pop %ebx
-	//      c3                      ret
-
-	o(0x53)
-
-	o(0xe8)
-	addcall(ctxt, initfunc, ctxt.Syms.Lookup("__x86.get_pc_thunk.cx", 0))
-
-	o(0x8d, 0x81)
-	initfunc.AddPCRelPlus(ctxt.Arch, ctxt.Moduledata, 6)
-
-	o(0x8d, 0x99)
-	i := initfunc.Size
-	initfunc.Size += 4
-	initfunc.Grow(initfunc.Size)
-	r := initfunc.AddRel()
-	r.Sym = ctxt.Syms.Lookup("_GLOBAL_OFFSET_TABLE_", 0)
-	r.Off = int32(i)
-	r.Type = objabi.R_PCREL
-	r.Add = 12
-	r.Siz = 4
-
-	o(0xe8)
-	addcall(ctxt, initfunc, addmoduledata)
-
-	o(0x5b)
-
-	o(0xc3)
-
-	if ctxt.BuildMode == ld.BuildModePlugin {
-		ctxt.Textp = append(ctxt.Textp, addmoduledata)
-	}
-	ctxt.Textp = append(ctxt.Textp, initfunc)
-	initarray_entry := ctxt.Syms.Lookup("go.link.addmoduledatainit", 0)
-	initarray_entry.Attr |= sym.AttrReachable
-	initarray_entry.Attr |= sym.AttrLocal
-	initarray_entry.Type = sym.SINITARR
-	initarray_entry.AddAddr(ctxt.Arch, initfunc)
-}
-
-func adddynrel(ctxt *ld.Link, s *sym.Symbol, r *sym.Reloc) bool {
-	targ := r.Sym
-
-	switch r.Type {
-	default:
-		if r.Type >= objabi.ElfRelocOffset {
-			ld.Errorf(s, "unexpected relocation type %d (%s)", r.Type, sym.RelocName(ctxt.Arch, r.Type))
-			return false
-		}
-
-		// Handle relocations found in ELF object files.
-	case objabi.ElfRelocOffset + objabi.RelocType(elf.R_386_PC32):
-		if targ.Type == sym.SDYNIMPORT {
-			ld.Errorf(s, "unexpected R_386_PC32 relocation for dynamic symbol %s", targ.Name)
-		}
-		// TODO(mwhudson): the test of VisibilityHidden here probably doesn't make
-		// sense and should be removed when someone has thought about it properly.
-		if (targ.Type == 0 || targ.Type == sym.SXREF) && !targ.Attr.VisibilityHidden() {
-			ld.Errorf(s, "unknown symbol %s in pcrel", targ.Name)
-		}
-		r.Type = objabi.R_PCREL
-		r.Add += 4
-		return true
-
-	case objabi.ElfRelocOffset + objabi.RelocType(elf.R_386_PLT32):
-		r.Type = objabi.R_PCREL
-		r.Add += 4
-		if targ.Type == sym.SDYNIMPORT {
-			addpltsym(ctxt, targ)
-			r.Sym = ctxt.Syms.Lookup(".plt", 0)
-			r.Add += int64(targ.Plt())
-		}
-
-		return true
-
-	case objabi.ElfRelocOffset + objabi.RelocType(elf.R_386_GOT32),
-		objabi.ElfRelocOffset + objabi.RelocType(elf.R_386_GOT32X):
-		if targ.Type != sym.SDYNIMPORT {
-			// have symbol
-			if r.Off >= 2 && s.P[r.Off-2] == 0x8b {
-				// turn MOVL of GOT entry into LEAL of symbol address, relative to GOT.
-				s.P[r.Off-2] = 0x8d
-
-				r.Type = objabi.R_GOTOFF
-				return true
-			}
-
-			if r.Off >= 2 && s.P[r.Off-2] == 0xff && s.P[r.Off-1] == 0xb3 {
-				// turn PUSHL of GOT entry into PUSHL of symbol itself.
-				// use unnecessary SS prefix to keep instruction same length.
-				s.P[r.Off-2] = 0x36
-
-				s.P[r.Off-1] = 0x68
-				r.Type = objabi.R_ADDR
-				return true
-			}
-
-			ld.Errorf(s, "unexpected GOT reloc for non-dynamic symbol %s", targ.Name)
-			return false
-		}
-
-		addgotsym(ctxt, targ)
-		r.Type = objabi.R_CONST // write r->add during relocsym
-		r.Sym = nil
-		r.Add += int64(targ.Got())
-		return true
-
-	case objabi.ElfRelocOffset + objabi.RelocType(elf.R_386_GOTOFF):
-		r.Type = objabi.R_GOTOFF
-		return true
-
-	case objabi.ElfRelocOffset + objabi.RelocType(elf.R_386_GOTPC):
-		r.Type = objabi.R_PCREL
-		r.Sym = ctxt.Syms.Lookup(".got", 0)
-		r.Add += 4
-		return true
-
-	case objabi.ElfRelocOffset + objabi.RelocType(elf.R_386_32):
-		if targ.Type == sym.SDYNIMPORT {
-			ld.Errorf(s, "unexpected R_386_32 relocation for dynamic symbol %s", targ.Name)
-		}
-		r.Type = objabi.R_ADDR
-		return true
-
-	case objabi.MachoRelocOffset + ld.MACHO_GENERIC_RELOC_VANILLA*2 + 0:
-		r.Type = objabi.R_ADDR
-		if targ.Type == sym.SDYNIMPORT {
-			ld.Errorf(s, "unexpected reloc for dynamic symbol %s", targ.Name)
-		}
-		return true
-
-	case objabi.MachoRelocOffset + ld.MACHO_GENERIC_RELOC_VANILLA*2 + 1:
-		if targ.Type == sym.SDYNIMPORT {
-			addpltsym(ctxt, targ)
-			r.Sym = ctxt.Syms.Lookup(".plt", 0)
-			r.Add = int64(targ.Plt())
-			r.Type = objabi.R_PCREL
-			return true
-		}
-
-		r.Type = objabi.R_PCREL
-		return true
-
-	case objabi.MachoRelocOffset + ld.MACHO_FAKE_GOTPCREL:
-		if targ.Type != sym.SDYNIMPORT {
-			// have symbol
-			// turn MOVL of GOT entry into LEAL of symbol itself
-			if r.Off < 2 || s.P[r.Off-2] != 0x8b {
-				ld.Errorf(s, "unexpected GOT reloc for non-dynamic symbol %s", targ.Name)
-				return false
-			}
-
-			s.P[r.Off-2] = 0x8d
-			r.Type = objabi.R_PCREL
-			return true
-		}
-
-		addgotsym(ctxt, targ)
-		r.Sym = ctxt.Syms.Lookup(".got", 0)
-		r.Add += int64(targ.Got())
-		r.Type = objabi.R_PCREL
-		return true
-	}
-
-	// Handle references to ELF symbols from our own object files.
-	if targ.Type != sym.SDYNIMPORT {
-		return true
-	}
-	switch r.Type {
-	case objabi.R_CALL,
-		objabi.R_PCREL:
-		if ctxt.LinkMode == ld.LinkExternal {
-			// External linker will do this relocation.
-			return true
-		}
-		addpltsym(ctxt, targ)
-		r.Sym = ctxt.Syms.Lookup(".plt", 0)
-		r.Add = int64(targ.Plt())
-		return true
-
-	case objabi.R_ADDR:
-		if s.Type != sym.SDATA {
-			break
-		}
-		if ctxt.IsELF {
-			ld.Adddynsym(ctxt, targ)
-			rel := ctxt.Syms.Lookup(".rel", 0)
-			rel.AddAddrPlus(ctxt.Arch, s, int64(r.Off))
-			rel.AddUint32(ctxt.Arch, ld.ELF32_R_INFO(uint32(targ.Dynid), uint32(elf.R_386_32)))
-			r.Type = objabi.R_CONST // write r->add during relocsym
-			r.Sym = nil
-			return true
-		}
-
-		if ctxt.HeadType == objabi.Hdarwin && s.Size == int64(ctxt.Arch.PtrSize) && r.Off == 0 {
-			// Mach-O relocations are a royal pain to lay out.
-			// They use a compact stateful bytecode representation
-			// that is too much bother to deal with.
-			// Instead, interpret the C declaration
-			//	void *_Cvar_stderr = &stderr;
-			// as making _Cvar_stderr the name of a GOT entry
-			// for stderr. This is separate from the usual GOT entry,
-			// just in case the C code assigns to the variable,
-			// and of course it only works for single pointers,
-			// but we only need to support cgo and that's all it needs.
-			ld.Adddynsym(ctxt, targ)
-
-			got := ctxt.Syms.Lookup(".got", 0)
-			s.Type = got.Type
-			s.Attr |= sym.AttrSubSymbol
-			s.Outer = got
-			s.Sub = got.Sub
-			got.Sub = s
-			s.Value = got.Size
-			got.AddUint32(ctxt.Arch, 0)
-			ctxt.Syms.Lookup(".linkedit.got", 0).AddUint32(ctxt.Arch, uint32(targ.Dynid))
-			r.Type = objabi.ElfRelocOffset // ignore during relocsym
-			return true
-		}
-	}
-
-	return false
-}
-
-func elfreloc1(ctxt *ld.Link, r *sym.Reloc, sectoff int64) bool {
-	ctxt.Out.Write32(uint32(sectoff))
-
-	elfsym := r.Xsym.ElfsymForReloc()
-	switch r.Type {
-	default:
-		return false
-	case objabi.R_ADDR:
-		if r.Siz == 4 {
-			ctxt.Out.Write32(uint32(elf.R_386_32) | uint32(elfsym)<<8)
-		} else {
-			return false
-		}
-	case objabi.R_GOTPCREL:
-		if r.Siz == 4 {
-			ctxt.Out.Write32(uint32(elf.R_386_GOTPC))
-			if r.Xsym.Name != "_GLOBAL_OFFSET_TABLE_" {
-				ctxt.Out.Write32(uint32(sectoff))
-				ctxt.Out.Write32(uint32(elf.R_386_GOT32) | uint32(elfsym)<<8)
-			}
-		} else {
-			return false
-		}
-	case objabi.R_CALL:
-		if r.Siz == 4 {
-			if r.Xsym.Type == sym.SDYNIMPORT {
-				ctxt.Out.Write32(uint32(elf.R_386_PLT32) | uint32(elfsym)<<8)
-			} else {
-				ctxt.Out.Write32(uint32(elf.R_386_PC32) | uint32(elfsym)<<8)
-			}
-		} else {
-			return false
-		}
-	case objabi.R_PCREL:
-		if r.Siz == 4 {
-			ctxt.Out.Write32(uint32(elf.R_386_PC32) | uint32(elfsym)<<8)
-		} else {
-			return false
-		}
-	case objabi.R_TLS_LE:
-		if r.Siz == 4 {
-			ctxt.Out.Write32(uint32(elf.R_386_TLS_LE) | uint32(elfsym)<<8)
-		} else {
-			return false
-		}
-	case objabi.R_TLS_IE:
-		if r.Siz == 4 {
-			ctxt.Out.Write32(uint32(elf.R_386_GOTPC))
-			ctxt.Out.Write32(uint32(sectoff))
-			ctxt.Out.Write32(uint32(elf.R_386_TLS_GOTIE) | uint32(elfsym)<<8)
-		} else {
-			return false
-		}
-	}
-
-	return true
-}
-
-func machoreloc1(arch *sys.Arch, out *ld.OutBuf, s *sym.Symbol, r *sym.Reloc, sectoff int64) bool {
-	return false
-}
-
-func pereloc1(arch *sys.Arch, out *ld.OutBuf, s *sym.Symbol, r *sym.Reloc, sectoff int64) bool {
-	var v uint32
-
-	rs := r.Xsym
-
-	if rs.Dynid < 0 {
-		ld.Errorf(s, "reloc %d (%s) to non-coff symbol %s type=%d (%s)", r.Type, sym.RelocName(arch, r.Type), rs.Name, rs.Type, rs.Type)
-		return false
-	}
-
-	out.Write32(uint32(sectoff))
-	out.Write32(uint32(rs.Dynid))
-
-	switch r.Type {
-	default:
-		return false
-
-	case objabi.R_DWARFSECREF:
-		v = ld.IMAGE_REL_I386_SECREL
-
-	case objabi.R_ADDR:
-		v = ld.IMAGE_REL_I386_DIR32
-
-	case objabi.R_CALL,
-		objabi.R_PCREL:
-		v = ld.IMAGE_REL_I386_REL32
-	}
-
-	out.Write16(uint16(v))
-
-	return true
-}
-
-func archreloc(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, val int64) (int64, bool) {
-	if ctxt.LinkMode == ld.LinkExternal {
-		return val, false
-	}
-	switch r.Type {
-	case objabi.R_CONST:
-		return r.Add, true
-	case objabi.R_GOTOFF:
-		return ld.Symaddr(r.Sym) + r.Add - ld.Symaddr(ctxt.Syms.Lookup(".got", 0)), true
-	}
-
-	return val, false
-}
-
-func archrelocvariant(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, t int64) int64 {
-	log.Fatalf("unexpected relocation variant")
-	return t
-}
-
-func elfsetupplt(ctxt *ld.Link) {
-	plt := ctxt.Syms.Lookup(".plt", 0)
-	got := ctxt.Syms.Lookup(".got.plt", 0)
-	if plt.Size == 0 {
-		// pushl got+4
-		plt.AddUint8(0xff)
-
-		plt.AddUint8(0x35)
-		plt.AddAddrPlus(ctxt.Arch, got, 4)
-
-		// jmp *got+8
-		plt.AddUint8(0xff)
-
-		plt.AddUint8(0x25)
-		plt.AddAddrPlus(ctxt.Arch, got, 8)
-
-		// zero pad
-		plt.AddUint32(ctxt.Arch, 0)
-
-		// assume got->size == 0 too
-		got.AddAddrPlus(ctxt.Arch, ctxt.Syms.Lookup(".dynamic", 0), 0)
-
-		got.AddUint32(ctxt.Arch, 0)
-		got.AddUint32(ctxt.Arch, 0)
-	}
-}
-
-func addpltsym(ctxt *ld.Link, s *sym.Symbol) {
-	if s.Plt() >= 0 {
-		return
-	}
-
-	ld.Adddynsym(ctxt, s)
-
-	if ctxt.IsELF {
-		plt := ctxt.Syms.Lookup(".plt", 0)
-		got := ctxt.Syms.Lookup(".got.plt", 0)
-		rel := ctxt.Syms.Lookup(".rel.plt", 0)
-		if plt.Size == 0 {
-			elfsetupplt(ctxt)
-		}
-
-		// jmpq *got+size
-		plt.AddUint8(0xff)
-
-		plt.AddUint8(0x25)
-		plt.AddAddrPlus(ctxt.Arch, got, got.Size)
-
-		// add to got: pointer to current pos in plt
-		got.AddAddrPlus(ctxt.Arch, plt, plt.Size)
-
-		// pushl $x
-		plt.AddUint8(0x68)
-
-		plt.AddUint32(ctxt.Arch, uint32(rel.Size))
-
-		// jmp .plt
-		plt.AddUint8(0xe9)
-
-		plt.AddUint32(ctxt.Arch, uint32(-(plt.Size + 4)))
-
-		// rel
-		rel.AddAddrPlus(ctxt.Arch, got, got.Size-4)
-
-		rel.AddUint32(ctxt.Arch, ld.ELF32_R_INFO(uint32(s.Dynid), uint32(elf.R_386_JMP_SLOT)))
-
-		s.SetPlt(int32(plt.Size - 16))
-	} else if ctxt.HeadType == objabi.Hdarwin {
-		// Same laziness as in 6l.
-
-		plt := ctxt.Syms.Lookup(".plt", 0)
-
-		addgotsym(ctxt, s)
-
-		ctxt.Syms.Lookup(".linkedit.plt", 0).AddUint32(ctxt.Arch, uint32(s.Dynid))
-
-		// jmpq *got+size(IP)
-		s.SetPlt(int32(plt.Size))
-
-		plt.AddUint8(0xff)
-		plt.AddUint8(0x25)
-		plt.AddAddrPlus(ctxt.Arch, ctxt.Syms.Lookup(".got", 0), int64(s.Got()))
-	} else {
-		ld.Errorf(s, "addpltsym: unsupported binary format")
-	}
-}
-
-func addgotsym(ctxt *ld.Link, s *sym.Symbol) {
-	if s.Got() >= 0 {
-		return
-	}
-
-	ld.Adddynsym(ctxt, s)
-	got := ctxt.Syms.Lookup(".got", 0)
-	s.SetGot(int32(got.Size))
-	got.AddUint32(ctxt.Arch, 0)
-
-	if ctxt.IsELF {
-		rel := ctxt.Syms.Lookup(".rel", 0)
-		rel.AddAddrPlus(ctxt.Arch, got, int64(s.Got()))
-		rel.AddUint32(ctxt.Arch, ld.ELF32_R_INFO(uint32(s.Dynid), uint32(elf.R_386_GLOB_DAT)))
-	} else if ctxt.HeadType == objabi.Hdarwin {
-		ctxt.Syms.Lookup(".linkedit.got", 0).AddUint32(ctxt.Arch, uint32(s.Dynid))
-	} else {
-		ld.Errorf(s, "addgotsym: unsupported binary format")
-	}
-}
-
-func asmb(ctxt *ld.Link) {
-	if ctxt.IsELF {
-		ld.Asmbelfsetup()
-	}
-
-	sect := ld.Segtext.Sections[0]
-	ctxt.Out.SeekSet(int64(sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff))
-	// 0xCC is INT $3 - breakpoint instruction
-	ld.CodeblkPad(ctxt, int64(sect.Vaddr), int64(sect.Length), []byte{0xCC})
-	for _, sect = range ld.Segtext.Sections[1:] {
-		ctxt.Out.SeekSet(int64(sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff))
-		ld.Datblk(ctxt, int64(sect.Vaddr), int64(sect.Length))
-	}
-
-	if ld.Segrodata.Filelen > 0 {
-		ctxt.Out.SeekSet(int64(ld.Segrodata.Fileoff))
-		ld.Datblk(ctxt, int64(ld.Segrodata.Vaddr), int64(ld.Segrodata.Filelen))
-	}
-	if ld.Segrelrodata.Filelen > 0 {
-		ctxt.Out.SeekSet(int64(ld.Segrelrodata.Fileoff))
-		ld.Datblk(ctxt, int64(ld.Segrelrodata.Vaddr), int64(ld.Segrelrodata.Filelen))
-	}
-
-	ctxt.Out.SeekSet(int64(ld.Segdata.Fileoff))
-	ld.Datblk(ctxt, int64(ld.Segdata.Vaddr), int64(ld.Segdata.Filelen))
-
-	ctxt.Out.SeekSet(int64(ld.Segdwarf.Fileoff))
-	ld.Dwarfblk(ctxt, int64(ld.Segdwarf.Vaddr), int64(ld.Segdwarf.Filelen))
-}
-
-func asmb2(ctxt *ld.Link) {
-	machlink := uint32(0)
-	if ctxt.HeadType == objabi.Hdarwin {
-		machlink = uint32(ld.Domacholink(ctxt))
-	}
-
-	ld.Symsize = 0
-	ld.Spsize = 0
-	ld.Lcsize = 0
-	symo := uint32(0)
-	if !*ld.FlagS {
-		// TODO: rationalize
-		switch ctxt.HeadType {
-		default:
-			if ctxt.IsELF {
-				symo = uint32(ld.Segdwarf.Fileoff + ld.Segdwarf.Filelen)
-				symo = uint32(ld.Rnd(int64(symo), int64(*ld.FlagRound)))
-			}
-
-		case objabi.Hplan9:
-			symo = uint32(ld.Segdata.Fileoff + ld.Segdata.Filelen)
-
-		case objabi.Hdarwin:
-			symo = uint32(ld.Segdwarf.Fileoff + uint64(ld.Rnd(int64(ld.Segdwarf.Filelen), int64(*ld.FlagRound))) + uint64(machlink))
-
-		case objabi.Hwindows:
-			symo = uint32(ld.Segdwarf.Fileoff + ld.Segdwarf.Filelen)
-			symo = uint32(ld.Rnd(int64(symo), ld.PEFILEALIGN))
-		}
-
-		ctxt.Out.SeekSet(int64(symo))
-		switch ctxt.HeadType {
-		default:
-			if ctxt.IsELF {
-				ld.Asmelfsym(ctxt)
-				ctxt.Out.Flush()
-				ctxt.Out.Write(ld.Elfstrdat)
-
-				if ctxt.LinkMode == ld.LinkExternal {
-					ld.Elfemitreloc(ctxt)
-				}
-			}
-
-		case objabi.Hplan9:
-			ld.Asmplan9sym(ctxt)
-			ctxt.Out.Flush()
-
-			sym := ctxt.Syms.Lookup("pclntab", 0)
-			if sym != nil {
-				ld.Lcsize = int32(len(sym.P))
-				ctxt.Out.Write(sym.P)
-				ctxt.Out.Flush()
-			}
-
-		case objabi.Hwindows:
-			// Do nothing
-
-		case objabi.Hdarwin:
-			if ctxt.LinkMode == ld.LinkExternal {
-				ld.Machoemitreloc(ctxt)
-			}
-		}
-	}
-
-	ctxt.Out.SeekSet(0)
-	switch ctxt.HeadType {
-	default:
-	case objabi.Hplan9: /* plan9 */
-		magic := int32(4*11*11 + 7)
-
-		ctxt.Out.Write32b(uint32(magic))              /* magic */
-		ctxt.Out.Write32b(uint32(ld.Segtext.Filelen)) /* sizes */
-		ctxt.Out.Write32b(uint32(ld.Segdata.Filelen))
-		ctxt.Out.Write32b(uint32(ld.Segdata.Length - ld.Segdata.Filelen))
-		ctxt.Out.Write32b(uint32(ld.Symsize))          /* nsyms */
-		ctxt.Out.Write32b(uint32(ld.Entryvalue(ctxt))) /* va of entry */
-		ctxt.Out.Write32b(uint32(ld.Spsize))           /* sp offsets */
-		ctxt.Out.Write32b(uint32(ld.Lcsize))           /* line offsets */
-
-	case objabi.Hdarwin:
-		ld.Asmbmacho(ctxt)
-
-	case objabi.Hlinux,
-		objabi.Hfreebsd,
-		objabi.Hnetbsd,
-		objabi.Hopenbsd:
-		ld.Asmbelf(ctxt, int64(symo))
-
-	case objabi.Hwindows:
-		ld.Asmbpe(ctxt)
-	}
-
-	ctxt.Out.Flush()
-}
diff --git a/src/cmd/oldlink/internal/x86/l.go b/src/cmd/oldlink/internal/x86/l.go
deleted file mode 100644
index 5875d45..0000000
--- a/src/cmd/oldlink/internal/x86/l.go
+++ /dev/null
@@ -1,43 +0,0 @@
-// Inferno utils/8l/l.h
-// https://bitbucket.org/inferno-os/inferno-os/src/master/utils/8l/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 x86
-
-const (
-	maxAlign  = 32 // max data alignment
-	minAlign  = 1  // min data alignment
-	funcAlign = 16
-)
-
-/* Used by ../internal/ld/dwarf.go */
-const (
-	dwarfRegSP = 4
-	dwarfRegLR = 8
-)
diff --git a/src/cmd/oldlink/internal/x86/obj.go b/src/cmd/oldlink/internal/x86/obj.go
deleted file mode 100644
index c9ec0bf..0000000
--- a/src/cmd/oldlink/internal/x86/obj.go
+++ /dev/null
@@ -1,113 +0,0 @@
-// Inferno utils/8l/obj.c
-// https://bitbucket.org/inferno-os/inferno-os/src/master/utils/8l/obj.c
-//
-//	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 x86
-
-import (
-	"cmd/internal/objabi"
-	"cmd/internal/sys"
-	"cmd/oldlink/internal/ld"
-)
-
-func Init() (*sys.Arch, ld.Arch) {
-	arch := sys.Arch386
-
-	theArch := ld.Arch{
-		Funcalign:  funcAlign,
-		Maxalign:   maxAlign,
-		Minalign:   minAlign,
-		Dwarfregsp: dwarfRegSP,
-		Dwarfreglr: dwarfRegLR,
-
-		Adddynrel:        adddynrel,
-		Archinit:         archinit,
-		Archreloc:        archreloc,
-		Archrelocvariant: archrelocvariant,
-		Asmb:             asmb,
-		Asmb2:            asmb2,
-		Elfreloc1:        elfreloc1,
-		Elfsetupplt:      elfsetupplt,
-		Gentext:          gentext,
-		Machoreloc1:      machoreloc1,
-		PEreloc1:         pereloc1,
-
-		Linuxdynld:   "/lib/ld-linux.so.2",
-		Freebsddynld: "/usr/libexec/ld-elf.so.1",
-		Openbsddynld: "/usr/libexec/ld.so",
-		Netbsddynld:  "/usr/libexec/ld.elf_so",
-		Solarisdynld: "/lib/ld.so.1",
-	}
-
-	return arch, theArch
-}
-
-func archinit(ctxt *ld.Link) {
-	switch ctxt.HeadType {
-	default:
-		ld.Exitf("unknown -H option: %v", ctxt.HeadType)
-
-	case objabi.Hplan9: /* plan 9 */
-		ld.HEADR = 32
-
-		if *ld.FlagTextAddr == -1 {
-			*ld.FlagTextAddr = 4096 + int64(ld.HEADR)
-		}
-		if *ld.FlagRound == -1 {
-			*ld.FlagRound = 4096
-		}
-
-	case objabi.Hdarwin: /* apple MACH */
-		ld.HEADR = ld.INITIAL_MACHO_HEADR
-		if *ld.FlagTextAddr == -1 {
-			*ld.FlagTextAddr = 4096 + int64(ld.HEADR)
-		}
-		if *ld.FlagRound == -1 {
-			*ld.FlagRound = 4096
-		}
-
-	case objabi.Hlinux, /* elf32 executable */
-		objabi.Hfreebsd,
-		objabi.Hnetbsd,
-		objabi.Hopenbsd:
-		ld.Elfinit(ctxt)
-
-		ld.HEADR = ld.ELFRESERVE
-		if *ld.FlagTextAddr == -1 {
-			*ld.FlagTextAddr = 0x08048000 + int64(ld.HEADR)
-		}
-		if *ld.FlagRound == -1 {
-			*ld.FlagRound = 4096
-		}
-
-	case objabi.Hwindows: /* PE executable */
-		// ld.HEADR, ld.FlagTextAddr, ld.FlagRound are set in ld.Peinit
-		return
-	}
-}
diff --git a/src/cmd/oldlink/main.go b/src/cmd/oldlink/main.go
deleted file mode 100644
index be1d0fd..0000000
--- a/src/cmd/oldlink/main.go
+++ /dev/null
@@ -1,71 +0,0 @@
-// Copyright 2015 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.
-
-// TODO(go115newobj): delete.
-
-package main
-
-import (
-	"cmd/internal/objabi"
-	"cmd/internal/sys"
-	"cmd/oldlink/internal/amd64"
-	"cmd/oldlink/internal/arm"
-	"cmd/oldlink/internal/arm64"
-	"cmd/oldlink/internal/ld"
-	"cmd/oldlink/internal/mips"
-	"cmd/oldlink/internal/mips64"
-	"cmd/oldlink/internal/ppc64"
-	"cmd/oldlink/internal/riscv64"
-	"cmd/oldlink/internal/s390x"
-	"cmd/oldlink/internal/wasm"
-	"cmd/oldlink/internal/x86"
-	"fmt"
-	"os"
-)
-
-// The bulk of the linker implementation lives in cmd/oldlink/internal/ld.
-// Architecture-specific code lives in cmd/oldlink/internal/GOARCH.
-//
-// Program initialization:
-//
-// Before any argument parsing is done, the Init function of relevant
-// architecture package is called. The only job done in Init is
-// configuration of the architecture-specific variables.
-//
-// Then control flow passes to ld.Main, which parses flags, makes
-// some configuration decisions, and then gives the architecture
-// packages a second chance to modify the linker's configuration
-// via the ld.Arch.Archinit function.
-
-func main() {
-	var arch *sys.Arch
-	var theArch ld.Arch
-
-	switch objabi.GOARCH {
-	default:
-		fmt.Fprintf(os.Stderr, "link: unknown architecture %q\n", objabi.GOARCH)
-		os.Exit(2)
-	case "386":
-		arch, theArch = x86.Init()
-	case "amd64":
-		arch, theArch = amd64.Init()
-	case "arm":
-		arch, theArch = arm.Init()
-	case "arm64":
-		arch, theArch = arm64.Init()
-	case "mips", "mipsle":
-		arch, theArch = mips.Init()
-	case "mips64", "mips64le":
-		arch, theArch = mips64.Init()
-	case "ppc64", "ppc64le":
-		arch, theArch = ppc64.Init()
-	case "riscv64":
-		arch, theArch = riscv64.Init()
-	case "s390x":
-		arch, theArch = s390x.Init()
-	case "wasm":
-		arch, theArch = wasm.Init()
-	}
-	ld.Main(arch, theArch)
-}