aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/link/internal/ld/go.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/link/internal/ld/go.go')
-rw-r--r--src/cmd/link/internal/ld/go.go163
1 files changed, 99 insertions, 64 deletions
diff --git a/src/cmd/link/internal/ld/go.go b/src/cmd/link/internal/ld/go.go
index 21457fdfc8..3b9d4ba7cc 100644
--- a/src/cmd/link/internal/ld/go.go
+++ b/src/cmd/link/internal/ld/go.go
@@ -10,6 +10,8 @@ import (
"bytes"
"cmd/internal/bio"
"cmd/internal/objabi"
+ "cmd/internal/sys"
+ "cmd/link/internal/loader"
"cmd/link/internal/sym"
"encoding/json"
"fmt"
@@ -145,16 +147,14 @@ func loadcgo(ctxt *Link, file string, pkg string, p string) {
}
}
- 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.
-func setCgoAttr(ctxt *Link, lookup func(string, int) *sym.Symbol, file string, pkg string, directives [][]string) {
+// Any newly discovered HOSTOBJ syms are added to 'hostObjSyms'.
+func setCgoAttr(ctxt *Link, lookup func(string, int) loader.Sym, file string, pkg string, directives [][]string, hostObjSyms map[loader.Sym]struct{}) {
+ l := ctxt.loader
for _, f := range directives {
switch f[0] {
case "cgo_import_dynamic":
@@ -197,12 +197,16 @@ func setCgoAttr(ctxt *Link, lookup func(string, int) *sym.Symbol, file string, p
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
+ st := l.SymType(s)
+ if st == 0 || st == sym.SXREF || st == sym.SBSS || st == sym.SNOPTRBSS || st == sym.SHOSTOBJ {
+ l.SetSymDynimplib(s, lib)
+ l.SetSymExtname(s, remote)
+ l.SetSymDynimpvers(s, q)
+ if st != sym.SHOSTOBJ {
+ su := l.MakeSymbolUpdater(s)
+ su.SetType(sym.SDYNIMPORT)
+ } else {
+ hostObjSyms[s] = struct{}{}
}
havedynamic = 1
}
@@ -216,8 +220,10 @@ func setCgoAttr(ctxt *Link, lookup func(string, int) *sym.Symbol, file string, p
local := f[1]
s := lookup(local, 0)
- s.Type = sym.SHOSTOBJ
- s.Size = 0
+ su := l.MakeSymbolUpdater(s)
+ su.SetType(sym.SHOSTOBJ)
+ su.SetSize(0)
+ hostObjSyms[s] = struct{}{}
continue
case "cgo_export_static", "cgo_export_dynamic":
@@ -238,6 +244,10 @@ func setCgoAttr(ctxt *Link, lookup func(string, int) *sym.Symbol, file string, p
// yet know it's an alias).
s := lookup(local, 0)
+ if l.SymType(s) == sym.SHOSTOBJ {
+ hostObjSyms[s] = struct{}{}
+ }
+
switch ctxt.BuildMode {
case BuildModeCShared, BuildModeCArchive, BuildModePlugin:
if s == lookup("main", 0) {
@@ -247,24 +257,27 @@ func setCgoAttr(ctxt *Link, lookup func(string, int) *sym.Symbol, file string, p
// export overrides import, for openbsd/cgo.
// see issue 4878.
- if s.Dynimplib() != "" {
- s.ResetDyninfo()
- s.SetExtname("")
- s.Type = 0
+ if l.SymDynimplib(s) != "" {
+ l.SetSymDynimplib(s, "")
+ l.SetSymDynimpvers(s, "")
+ l.SetSymExtname(s, "")
+ var su *loader.SymbolBuilder
+ su = l.MakeSymbolUpdater(s)
+ su.SetType(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)
+ if !(l.AttrCgoExportStatic(s) || l.AttrCgoExportDynamic(s)) {
+ l.SetSymExtname(s, remote)
+ } else if l.SymExtname(s) != remote {
+ fmt.Fprintf(os.Stderr, "%s: conflicting cgo_export directives: %s as %s and %s\n", os.Args[0], l.SymName(s), l.SymExtname(s), remote)
nerrors++
return
}
if f[0] == "cgo_export_static" {
- s.Attr |= sym.AttrCgoExportStatic
+ l.SetAttrCgoExportStatic(s, true)
} else {
- s.Attr |= sym.AttrCgoExportDynamic
+ l.SetAttrCgoExportDynamic(s, true)
}
continue
@@ -295,6 +308,7 @@ func setCgoAttr(ctxt *Link, lookup func(string, int) *sym.Symbol, file string, p
fmt.Fprintf(os.Stderr, "%s: %s: invalid cgo directive: %q\n", os.Args[0], file, f)
nerrors++
}
+ return
}
var seenlib = make(map[string]bool)
@@ -306,78 +320,99 @@ func adddynlib(ctxt *Link, lib string) {
seenlib[lib] = true
if ctxt.IsELF {
- s := ctxt.Syms.Lookup(".dynstr", 0)
- if s.Size == 0 {
- Addstring(s, "")
+ dsu := ctxt.loader.MakeSymbolUpdater(ctxt.DynStr2)
+ if dsu.Size() == 0 {
+ dsu.Addstring("")
}
- Elfwritedynent(ctxt, ctxt.Syms.Lookup(".dynamic", 0), DT_NEEDED, uint64(Addstring(s, lib)))
+ du := ctxt.loader.MakeSymbolUpdater(ctxt.Dynamic2)
+ Elfwritedynent2(ctxt.Arch, du, DT_NEEDED, uint64(dsu.Addstring(lib)))
} else {
Errorf(nil, "adddynlib: unsupported binary format")
}
}
-func Adddynsym(ctxt *Link, s *sym.Symbol) {
- if s.Dynid >= 0 || ctxt.LinkMode == LinkExternal {
+func Adddynsym2(ldr *loader.Loader, reporter *ErrorReporter, target *Target, syms *ArchSyms, s loader.Sym) {
+ if ldr.SymDynid(s) >= 0 || target.LinkMode == LinkExternal {
return
}
- if ctxt.IsELF {
- elfadddynsym(ctxt, s)
- } else if ctxt.HeadType == objabi.Hdarwin {
+ if target.IsELF {
+ elfadddynsym2(ldr, target, syms, s)
+ } else if target.HeadType == objabi.Hdarwin {
+ reporter.Errorf(s, "adddynsym: missed symbol (Extname=%s)", ldr.SymExtname(s))
+ } else if target.HeadType == objabi.Hwindows {
+ // already taken care of
+ } else {
+ reporter.Errorf(s, "adddynsym: unsupported binary format")
+ }
+}
+
+func Adddynsym(target *Target, syms *ArchSyms, s *sym.Symbol) {
+ if s.Dynid >= 0 || target.LinkMode == LinkExternal {
+ return
+ }
+
+ if target.IsELF {
+ elfadddynsym(target, syms, s)
+ } else if target.HeadType == objabi.Hdarwin {
Errorf(s, "adddynsym: missed symbol (Extname=%s)", s.Extname())
- } else if ctxt.HeadType == objabi.Hwindows {
+ } else if target.HeadType == objabi.Hwindows {
// already taken care of
} else {
Errorf(s, "adddynsym: unsupported binary format")
}
}
-func fieldtrack(ctxt *Link) {
- // record field tracking references
+func fieldtrack(arch *sys.Arch, l *loader.Loader) {
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] {
+ 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() {
+ buf.WriteString(name[9:])
+ for p := l.Reachparent[i]; p != 0; p = l.Reachparent[p] {
buf.WriteString("\t")
- buf.WriteString(p.Name)
+ buf.WriteString(l.SymName(p))
}
buf.WriteString("\n")
- }
- s.Type = sym.SCONST
- s.Value = 0
+ bld.SetType(sym.SCONST)
+ bld.SetValue(0)
+ }
}
}
-
if *flagFieldTrack == "" {
return
}
- s := ctxt.Syms.ROLookup(*flagFieldTrack, 0)
- if s == nil || !s.Attr.Reachable() {
+ s := l.Lookup(*flagFieldTrack, 0)
+ if s == 0 || !l.AttrReachable(s) {
return
}
- s.Type = sym.SDATA
- addstrdata(ctxt, *flagFieldTrack, buf.String())
+ bld := l.MakeSymbolUpdater(s)
+ bld.SetType(sym.SDATA)
+ addstrdata(arch, l, *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 {
+ for _, s := range ctxt.Textp2 {
+ if ctxt.loader.AttrSpecial(s) || ctxt.loader.AttrSubSymbol(s) {
continue
}
- for i := range s.R {
- r := &s.R[i]
- if r.Sym != nil && r.Sym.Type == sym.Sxxx {
- r.Sym.Type = sym.SUNDEFEXT
+ relocs := ctxt.loader.Relocs(s)
+ for i := 0; i < relocs.Count(); i++ {
+ if rs := relocs.At2(i).Sym(); rs != 0 {
+ if ctxt.loader.SymType(rs) == sym.Sxxx && !ctxt.loader.AttrLocal(rs) {
+ // sanity check
+ if len(ctxt.loader.Data(rs)) != 0 {
+ panic("expected no data on undef symbol")
+ }
+ su := ctxt.loader.MakeSymbolUpdater(rs)
+ su.SetType(sym.SUNDEFEXT)
+ }
}
}
}
@@ -388,8 +423,8 @@ func (ctxt *Link) addexport() {
return
}
- for _, exp := range dynexp {
- Adddynsym(ctxt, exp)
+ for _, exp := range ctxt.dynexp2 {
+ Adddynsym2(ctxt.loader, &ctxt.ErrorReporter, &ctxt.Target, &ctxt.ArchSyms, exp)
}
for _, lib := range dynlib {
adddynlib(ctxt, lib)