diff options
Diffstat (limited to 'src/cmd/link/internal/ld/go.go')
-rw-r--r-- | src/cmd/link/internal/ld/go.go | 163 |
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) |