[dev.link] all: merge branch 'master' into dev.link
Clean merge.
Change-Id: I4a73cd4bac2f4d35d2c07c39f2bc01c6075fadab
diff --git a/src/cmd/asm/internal/flags/flags.go b/src/cmd/asm/internal/flags/flags.go
index fad87b2..5fe3fd9 100644
--- a/src/cmd/asm/internal/flags/flags.go
+++ b/src/cmd/asm/internal/flags/flags.go
@@ -23,7 +23,6 @@
Dynlink = flag.Bool("dynlink", false, "support references to Go symbols defined in other shared libraries")
AllErrors = flag.Bool("e", false, "no limit on number of errors reported")
SymABIs = flag.Bool("gensymabis", false, "write symbol ABI information to output file, don't assemble")
- Newobj = flag.Bool("newobj", false, "use new object file format")
)
var (
diff --git a/src/cmd/asm/main.go b/src/cmd/asm/main.go
index 6b0a609..51f9950 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_newobj = *flags.Newobj
ctxt.Bso = bufio.NewWriter(os.Stdout)
defer ctxt.Bso.Flush()
diff --git a/src/cmd/compile/internal/gc/iexport.go b/src/cmd/compile/internal/gc/iexport.go
index 259b70a..7d2fa3f 100644
--- a/src/cmd/compile/internal/gc/iexport.go
+++ b/src/cmd/compile/internal/gc/iexport.go
@@ -991,18 +991,16 @@
}
func (w *exportWriter) symIdx(s *types.Sym) {
- if Ctxt.Flag_newobj {
- 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 824648a..a9d29f1 100644
--- a/src/cmd/compile/internal/gc/iimport.go
+++ b/src/cmd/compile/internal/gc/iimport.go
@@ -687,16 +687,14 @@
}
func (r *importReader) symIdx(s *types.Sym) {
- if Ctxt.Flag_newobj {
- 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 4b6c8f2..c92f5ec 100644
--- a/src/cmd/compile/internal/gc/main.go
+++ b/src/cmd/compile/internal/gc/main.go
@@ -277,7 +277,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_newobj, "newobj", false, "use new object file format")
flag.StringVar(&jsonLogOpt, "json", "", "version,destination for JSON compiler/optimizer logging")
objabi.Flagparse(usage)
@@ -285,7 +284,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", "newobj")
+ recordFlags("B", "N", "l", "msan", "race", "shared", "dynlink", "dwarflocationlists", "dwarfbasentries", "smallframes")
if smallFrames {
maxStackVarSize = 128 * 1024
diff --git a/src/cmd/dist/buildtool.go b/src/cmd/dist/buildtool.go
index d30529b..12baccb 100644
--- a/src/cmd/dist/buildtool.go
+++ b/src/cmd/dist/buildtool.go
@@ -80,7 +80,6 @@
"cmd/link/internal/loadxcoff",
"cmd/link/internal/mips",
"cmd/link/internal/mips64",
- "cmd/link/internal/objfile",
"cmd/link/internal/ppc64",
"cmd/link/internal/riscv64",
"cmd/link/internal/s390x",
diff --git a/src/cmd/internal/obj/link.go b/src/cmd/internal/obj/link.go
index 76c6f26..b96da1b 100644
--- a/src/cmd/internal/obj/link.go
+++ b/src/cmd/internal/obj/link.go
@@ -652,7 +652,6 @@
Flag_linkshared bool
Flag_optimize bool
Flag_locationlists bool
- Flag_newobj bool // use new object file format
Bso *bufio.Writer
Pathname string
hashmu sync.Mutex // protects hash, funchash
diff --git a/src/cmd/internal/obj/objfile.go b/src/cmd/internal/obj/objfile.go
index 76fbc58..139c16a 100644
--- a/src/cmd/internal/obj/objfile.go
+++ b/src/cmd/internal/obj/objfile.go
@@ -7,225 +7,17 @@
package obj
import (
- "bufio"
"cmd/internal/bio"
"cmd/internal/dwarf"
"cmd/internal/objabi"
"cmd/internal/sys"
"fmt"
- "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_newobj {
- 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 _, pkg := range ctxt.Imports {
- w.writeString(pkg)
- }
- w.writeString("")
-
- // DWARF File Table
- fileTable := ctxt.PosTable.DebugLinesFileTable()
- w.writeInt(int64(len(fileTable)))
- for _, str := range fileTable {
- w.writeString(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)
- }
- }
+ WriteObjFile2(ctxt, bout, pkgpath)
}
func (ctxt *Link) writeSymDebug(s *LSym) {
@@ -305,137 +97,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.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
diff --git a/src/cmd/internal/obj/sym.go b/src/cmd/internal/obj/sym.go
index 3ef8866..e1e749d 100644
--- a/src/cmd/internal/obj/sym.go
+++ b/src/cmd/internal/obj/sym.go
@@ -164,10 +164,6 @@
// 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_newobj {
- return
- }
-
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
diff --git a/src/cmd/link/internal/amd64/asm.go b/src/cmd/link/internal/amd64/asm.go
index 991f552..0f0dcc4 100644
--- a/src/cmd/link/internal/amd64/asm.go
+++ b/src/cmd/link/internal/amd64/asm.go
@@ -98,6 +98,14 @@
initarray_entry.AddAddr(ctxt.Arch, initfunc)
}
+// 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 adddynrel(ctxt *ld.Link, s *sym.Symbol, r *sym.Reloc) bool {
targ := r.Sym
@@ -219,6 +227,7 @@
return false
}
+ makeWritable(s)
s.P[r.Off-2] = 0x8d
r.Type = objabi.R_PCREL
return true
diff --git a/src/cmd/link/internal/ld/deadcode.go b/src/cmd/link/internal/ld/deadcode.go
index e79207e..4a53d79 100644
--- a/src/cmd/link/internal/ld/deadcode.go
+++ b/src/cmd/link/internal/ld/deadcode.go
@@ -6,11 +6,7 @@
import (
"cmd/internal/objabi"
- "cmd/internal/sys"
"cmd/link/internal/sym"
- "fmt"
- "strings"
- "unicode"
)
// deadcode marks all reachable symbols.
@@ -46,84 +42,7 @@
//
// 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()
-
- callSym := ctxt.Syms.ROLookup("reflect.Value.Call", sym.SymVerABIInternal)
- methSym := ctxt.Syms.ROLookup("reflect.Value.Method", 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 || (callSym != nil && callSym.Attr.Reachable()) || (methSym != nil && methSym.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)
+ deadcode2(ctxt)
}
func addToTextp(ctxt *Link) {
@@ -188,221 +107,3 @@
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 an 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/link/internal/ld/go.go b/src/cmd/link/internal/ld/go.go
index 21457fd..a9dde22 100644
--- a/src/cmd/link/internal/ld/go.go
+++ b/src/cmd/link/internal/ld/go.go
@@ -145,12 +145,8 @@
}
}
- 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)
- }
+ // Record the directives. We'll process them later after Symbols are created.
+ ctxt.cgodata = append(ctxt.cgodata, cgodata{file, pkg, directives})
}
// Set symbol attributes or flags based on cgo directives.
diff --git a/src/cmd/link/internal/ld/lib.go b/src/cmd/link/internal/ld/lib.go
index 45cc872..20852b5 100644
--- a/src/cmd/link/internal/ld/lib.go
+++ b/src/cmd/link/internal/ld/lib.go
@@ -42,7 +42,6 @@
"cmd/link/internal/loadmacho"
"cmd/link/internal/loadpe"
"cmd/link/internal/loadxcoff"
- "cmd/link/internal/objfile"
"cmd/link/internal/sym"
"crypto/sha1"
"debug/elf"
@@ -380,18 +379,16 @@
}
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)
+ 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)
@@ -426,13 +423,8 @@
}
}
- 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
- }
+ iscgo = ctxt.loader.Lookup("x_cgo_init", 0) != 0
+ ctxt.canUsePlugins = ctxt.loader.Lookup("plugin.Open", sym.SymVerABIInternal) != 0
// We now have enough information to determine the link mode.
determineLinkMode(ctxt)
@@ -464,18 +456,16 @@
}
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
+ // 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.
@@ -498,15 +488,8 @@
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)
- }
+ // Add references of externally defined symbols.
+ ctxt.loader.LoadRefs(ctxt.Arch, ctxt.Syms)
if ctxt.LinkMode == LinkInternal && len(hostobj) != 0 {
// If we have any undefined symbols in external
@@ -563,9 +546,7 @@
importcycles()
- if *flagNewobj {
- strictDupMsgCount = ctxt.loader.NStrictDupMsgs()
- }
+ strictDupMsgCount = ctxt.loader.NStrictDupMsgs()
}
// Set up dynexp list.
@@ -1692,107 +1673,55 @@
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...)
+ 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
}
- 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)
+ 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...)
+ 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
}
- 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)
+ 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...)
+ 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
}
- 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...)
+ if rsrc != nil {
+ setpersrc(ctxt, rsrc)
}
- return ldhostobj(ldpe, ctxt.HeadType, f, pkg, length, pn, file)
+ 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...)
+ 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
}
- 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)
+ ctxt.Textp = append(ctxt.Textp, textp...)
}
+ return ldhostobj(ldxcoff, ctxt.HeadType, f, pkg, length, pn, file)
}
/* check the header */
@@ -1877,24 +1806,7 @@
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
+ ctxt.loader.Preload(ctxt.Arch, ctxt.Syms, f, lib, unit, eof-f.Offset(), pn, 0)
addImports(ctxt, lib, pn)
return nil
}
@@ -2048,17 +1960,13 @@
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)
+ i := ctxt.loader.AddExtSym(elfsym.Name, ver)
+ if i == 0 {
+ continue
}
+ lsym := ctxt.Syms.Newsym(elfsym.Name, ver)
+ ctxt.loader.Syms[i] = lsym
+
// 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
@@ -2087,17 +1995,12 @@
// 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)
+ 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
if alias.Type != 0 {
continue
}
diff --git a/src/cmd/link/internal/ld/main.go b/src/cmd/link/internal/ld/main.go
index 9f9395b..299a0a1 100644
--- a/src/cmd/link/internal/ld/main.go
+++ b/src/cmd/link/internal/ld/main.go
@@ -87,7 +87,6 @@
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`")
@@ -210,9 +209,7 @@
ctxt.loadlib()
deadcode(ctxt)
- if *flagNewobj {
- ctxt.loadlibfull() // XXX do it here for now
- }
+ ctxt.loadlibfull() // XXX do it here for now
ctxt.linksetup()
ctxt.dostrdata()
diff --git a/src/cmd/link/internal/loadelf/ldelf.go b/src/cmd/link/internal/loadelf/ldelf.go
index 072eaf0..c32f32c 100644
--- a/src/cmd/link/internal/loadelf/ldelf.go
+++ b/src/cmd/link/internal/loadelf/ldelf.go
@@ -452,20 +452,7 @@
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.LookupOrCreate(name, version, syms)
- }
- return load(arch, syms.IncVersion(), newSym, newSym, f, pkg, length, pn, flags)
-}
-
-func LoadOld(arch *sys.Arch, syms *sym.Symbols, f *bio.Reader, pkg string, length int64, pn string, flags uint32) ([]*sym.Symbol, uint32, error) {
- return load(arch, syms.IncVersion(), syms.Newsym, syms.Lookup, f, pkg, length, pn, flags)
-}
-
-type lookupFunc func(string, int) *sym.Symbol
-
-// load loads the ELF file pn from f.
+// Load loads the ELF file pn from f.
// Symbols are written into syms, and a slice of the text symbols is returned.
//
// On ARM systems, Load will attempt to determine what ELF header flags to
@@ -473,7 +460,11 @@
// parameter initEhdrFlags contains the current header flags for the output
// object, and the returned ehdrFlags contains what this Load function computes.
// TODO: find a better place for this logic.
-func load(arch *sys.Arch, localSymVersion int, newSym, lookup lookupFunc, f *bio.Reader, pkg string, length int64, pn string, initEhdrFlags uint32) (textp []*sym.Symbol, ehdrFlags uint32, err error) {
+func Load(l *loader.Loader, arch *sys.Arch, syms *sym.Symbols, f *bio.Reader, pkg string, length int64, pn string, initEhdrFlags uint32) (textp []*sym.Symbol, ehdrFlags uint32, err error) {
+ localSymVersion := syms.IncVersion()
+ lookup := func(name string, version int) *sym.Symbol {
+ return l.LookupOrCreate(name, version, syms)
+ }
errorf := func(str string, args ...interface{}) ([]*sym.Symbol, uint32, error) {
return nil, 0, fmt.Errorf("loadelf: %s: %v", pn, fmt.Sprintf(str, args...))
}
@@ -767,7 +758,7 @@
for i := 1; i < elfobj.nsymtab; i++ {
var elfsym ElfSym
- if err := readelfsym(newSym, lookup, arch, elfobj, i, &elfsym, 1, localSymVersion); err != nil {
+ if err := readelfsym(lookup, arch, elfobj, i, &elfsym, 1, localSymVersion); err != nil {
return errorf("%s: malformed elf file: %v", pn, err)
}
symbols[i] = elfsym.sym
@@ -938,7 +929,7 @@
rp.Sym = nil
} else {
var elfsym ElfSym
- if err := readelfsym(newSym, lookup, arch, elfobj, int(info>>32), &elfsym, 0, 0); err != nil {
+ if err := readelfsym(lookup, arch, elfobj, int(info>>32), &elfsym, 0, 0); err != nil {
return errorf("malformed elf file: %v", err)
}
elfsym.sym = symbols[info>>32]
@@ -1015,7 +1006,7 @@
return nil
}
-func readelfsym(newSym, lookup lookupFunc, arch *sys.Arch, elfobj *ElfObj, i int, elfsym *ElfSym, needSym int, localSymVersion int) (err error) {
+func readelfsym(lookup func(string, int) *sym.Symbol, arch *sys.Arch, elfobj *ElfObj, i int, elfsym *ElfSym, needSym int, localSymVersion int) (err error) {
if i >= elfobj.nsymtab || i < 0 {
err = fmt.Errorf("invalid elf symbol index")
return err
@@ -1101,7 +1092,7 @@
// local names and hidden global names are unique
// and should only be referenced by their index, not name, so we
// don't bother to add them into the hash table
- s = newSym(elfsym.name, localSymVersion)
+ s = lookup(elfsym.name, localSymVersion)
s.Attr |= sym.AttrVisibilityHidden
}
diff --git a/src/cmd/link/internal/loader/loader.go b/src/cmd/link/internal/loader/loader.go
index c0fa5fa..4fa0d5d 100644
--- a/src/cmd/link/internal/loader/loader.go
+++ b/src/cmd/link/internal/loader/loader.go
@@ -1058,7 +1058,7 @@
rs = 0
sz = 0
}
- if rs != 0 && l.SymType(rs) == sym.SABIALIAS {
+ if rs != 0 && l.Syms[rs] != nil && l.Syms[rs].Type == sym.SABIALIAS {
rsrelocs := l.Relocs(rs)
rs = rsrelocs.At(0).Sym
}
diff --git a/src/cmd/link/internal/loadmacho/ldmacho.go b/src/cmd/link/internal/loadmacho/ldmacho.go
index 85a1ebc..a98b962 100644
--- a/src/cmd/link/internal/loadmacho/ldmacho.go
+++ b/src/cmd/link/internal/loadmacho/ldmacho.go
@@ -14,7 +14,6 @@
"cmd/link/internal/sym"
"encoding/binary"
"fmt"
- "io"
"sort"
)
@@ -320,10 +319,9 @@
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 {
+ buf, _, err := m.f.Slice(uint64(sect.nreloc * 8))
+ if err != nil {
return -1
}
for i := uint32(0); i < sect.nreloc; i++ {
@@ -364,10 +362,9 @@
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 {
+ p, _, err := m.f.Slice(uint64(n * 4))
+ if err != nil {
return -1
}
@@ -383,9 +380,9 @@
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 {
+ strbuf, _, err := m.f.Slice(uint64(symtab.strsize))
+ if err != nil {
return -1
}
@@ -394,9 +391,9 @@
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 {
+ symbuf, _, err := m.f.Slice(uint64(n))
+ if err != nil {
return -1
}
sym := make([]ldMachoSym, symtab.nsym)
@@ -424,28 +421,18 @@
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.
+// 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) {
+func Load(l *loader.Loader, arch *sys.Arch, syms *sym.Symbols, f *bio.Reader, pkg string, length int64, pn string) (textp []*sym.Symbol, err error) {
+ localSymVersion := syms.IncVersion()
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 {
+ hdr, _, err := f.Slice(7 * 4)
+ if err != nil {
return errorf("reading hdr: %v", err)
}
@@ -499,8 +486,8 @@
}
m.cmd = make([]ldMachoCmd, ncmd)
- cmdp := make([]byte, cmdsz)
- if _, err := io.ReadFull(f, cmdp); err != nil {
+ cmdp, _, err := f.Slice(uint64(cmdsz))
+ if err != nil {
return errorf("reading cmds: %v", err)
}
@@ -559,8 +546,8 @@
}
f.MustSeek(m.base+int64(c.seg.fileoff), 0)
- dat := make([]byte, c.seg.filesz)
- if _, err := io.ReadFull(f, dat); err != nil {
+ dat, readOnly, err := f.Slice(uint64(c.seg.filesz))
+ if err != nil {
return errorf("cannot load object data: %v", err)
}
@@ -573,7 +560,7 @@
continue
}
name := fmt.Sprintf("%s(%s/%s)", pkg, sect.segname, sect.name)
- s := lookup(name, localSymVersion)
+ s := l.LookupOrCreate(name, localSymVersion, syms)
if s.Type != 0 {
return errorf("duplicate %s/%s", sect.segname, sect.name)
}
@@ -581,6 +568,7 @@
if sect.flags&0xff == 1 { // S_ZEROFILL
s.P = make([]byte, sect.size)
} else {
+ s.Attr.Set(sym.AttrReadOnly, readOnly)
s.P = dat[sect.addr-c.seg.vmaddr:][:sect.size]
}
s.Size = int64(len(s.P))
@@ -621,7 +609,7 @@
if machsym.type_&N_EXT == 0 {
v = localSymVersion
}
- s := lookup(name, v)
+ s := l.LookupOrCreate(name, v, syms)
if machsym.type_&N_EXT == 0 {
s.Attr |= sym.AttrDuplicateOK
}
diff --git a/src/cmd/link/internal/loadpe/ldpe.go b/src/cmd/link/internal/loadpe/ldpe.go
index 8b6aac3..ab3aeef 100644
--- a/src/cmd/link/internal/loadpe/ldpe.go
+++ b/src/cmd/link/internal/loadpe/ldpe.go
@@ -145,21 +145,14 @@
return n, nil
}
+// 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(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) {
+ localSymVersion := syms.IncVersion()
sectsyms := make(map[*pe.Section]*sym.Symbol)
sectdata := make(map[*pe.Section][]byte)
diff --git a/src/cmd/link/internal/loadxcoff/ldxcoff.go b/src/cmd/link/internal/loadxcoff/ldxcoff.go
index 759b176..f0e3567 100644
--- a/src/cmd/link/internal/loadxcoff/ldxcoff.go
+++ b/src/cmd/link/internal/loadxcoff/ldxcoff.go
@@ -39,22 +39,10 @@
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) {
+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) {
+ localSymVersion := syms.IncVersion()
errorf := func(str string, args ...interface{}) ([]*sym.Symbol, error) {
return nil, fmt.Errorf("loadxcoff: %v: %v", pn, fmt.Sprintf(str, args...))
}
@@ -75,7 +63,7 @@
lds := new(ldSection)
lds.Section = *sect
name := fmt.Sprintf("%s(%s)", pkg, lds.Name)
- s := lookup(name, localSymVersion)
+ s := l.LookupOrCreate(name, localSymVersion, syms)
switch lds.Type {
default:
@@ -113,7 +101,7 @@
continue
}
- s := lookup(sx.Name, 0)
+ s := l.LookupOrCreate(sx.Name, 0, syms)
// Text symbol
if s.Type == sym.STEXT {
@@ -135,7 +123,7 @@
for i, rx := range sect.Relocs {
r := &rs[i]
- r.Sym = lookup(rx.Symbol.Name, 0)
+ r.Sym = l.LookupOrCreate(rx.Symbol.Name, 0, syms)
if uint64(int32(rx.VirtualAddress)) != rx.VirtualAddress {
return errorf("virtual address of a relocation is too big: 0x%x", rx.VirtualAddress)
}
diff --git a/src/cmd/link/internal/objfile/objfile.go b/src/cmd/link/internal/objfile/objfile.go
deleted file mode 100644
index a15d3c3..0000000
--- a/src/cmd/link/internal/objfile/objfile.go
+++ /dev/null
@@ -1,659 +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/obj"
- "cmd/internal/objabi"
- "cmd/internal/sys"
- "cmd/link/internal/sym"
- "fmt"
- "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 {
- 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()
- 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, whitelist 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.
- whitelist := (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 !whitelist {
- 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
-}
-
-type stringHeader struct {
- str unsafe.Pointer
- len int
-}
-
-func mkROString(rodata []byte) string {
- if len(rodata) == 0 {
- return ""
- }
- ss := stringHeader{str: unsafe.Pointer(&rodata[0]), len: len(rodata)}
- s := *(*string)(unsafe.Pointer(&ss))
- 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]
-}