]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.link] cmd/link: convert addexport to loader interfaces
authorThan McIntosh <thanm@google.com>
Tue, 24 Mar 2020 13:05:19 +0000 (09:05 -0400)
committerThan McIntosh <thanm@google.com>
Wed, 25 Mar 2020 12:47:41 +0000 (12:47 +0000)
Convert the linker's "addexport" function to use loader interfaces
for symbol manipulation instead of *sym.Symbol.

At the moment "addexport" happens after loadlibfull (there are other
chunks of functionality in the way that haven't been converted), so
this implementation contains temporary shim code to copy back the
contents of updated loader.Sym's into the corresponding sym.Symbol.

Change-Id: I867b08e66562a2bed51560fd0be2cb64d344709c
Reviewed-on: https://go-review.googlesource.com/c/go/+/224384
Run-TryBot: Than McIntosh <thanm@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
src/cmd/link/internal/ld/elf.go
src/cmd/link/internal/ld/go.go

index 28802f1bd8c10e29bef9a740f468f0c04ae0f365..c5c07d63f7eb9e70ab17803b1f598000d28fb1e7 100644 (file)
@@ -776,13 +776,13 @@ func elfWriteDynEntSymSize(arch *sys.Arch, s *sym.Symbol, tag int, t *sym.Symbol
 }
 
 // temporary
-func Elfwritedynent2(ctxt *Link, s *loader.SymbolBuilder, tag int, val uint64) {
+func Elfwritedynent2(arch *sys.Arch, s *loader.SymbolBuilder, tag int, val uint64) {
        if elf64 {
-               s.AddUint64(ctxt.Arch, uint64(tag))
-               s.AddUint64(ctxt.Arch, val)
+               s.AddUint64(arch, uint64(tag))
+               s.AddUint64(arch, val)
        } else {
-               s.AddUint32(ctxt.Arch, uint32(tag))
-               s.AddUint32(ctxt.Arch, uint32(val))
+               s.AddUint32(arch, uint32(tag))
+               s.AddUint32(arch, uint32(val))
        }
 }
 
@@ -1658,9 +1658,9 @@ func (ctxt *Link) doelf() {
 
                elfwritedynentsym2(ctxt, dynamic, DT_SYMTAB, dynsym.Sym())
                if elf64 {
-                       Elfwritedynent2(ctxt, dynamic, DT_SYMENT, ELF64SYMSIZE)
+                       Elfwritedynent2(ctxt.Arch, dynamic, DT_SYMENT, ELF64SYMSIZE)
                } else {
-                       Elfwritedynent2(ctxt, dynamic, DT_SYMENT, ELF32SYMSIZE)
+                       Elfwritedynent2(ctxt.Arch, dynamic, DT_SYMENT, ELF32SYMSIZE)
                }
                elfwritedynentsym2(ctxt, dynamic, DT_STRTAB, dynstr.Sym())
                elfwritedynentsymsize2(ctxt, dynamic, DT_STRSZ, dynstr.Sym())
@@ -1668,16 +1668,16 @@ func (ctxt *Link) doelf() {
                        rela := ldr.LookupOrCreateSym(".rela", 0)
                        elfwritedynentsym2(ctxt, dynamic, DT_RELA, rela)
                        elfwritedynentsymsize2(ctxt, dynamic, DT_RELASZ, rela)
-                       Elfwritedynent2(ctxt, dynamic, DT_RELAENT, ELF64RELASIZE)
+                       Elfwritedynent2(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, dynamic, DT_RELENT, ELF32RELSIZE)
+                       Elfwritedynent2(ctxt.Arch, dynamic, DT_RELENT, ELF32RELSIZE)
                }
 
                if rpath.val != "" {
-                       Elfwritedynent2(ctxt, dynamic, DT_RUNPATH, uint64(dynstr.Addstring(rpath.val)))
+                       Elfwritedynent2(ctxt.Arch, dynamic, DT_RUNPATH, uint64(dynstr.Addstring(rpath.val)))
                }
 
                if ctxt.IsPPC64() {
@@ -1687,14 +1687,14 @@ func (ctxt *Link) doelf() {
                }
 
                if ctxt.IsPPC64() {
-                       Elfwritedynent2(ctxt, dynamic, DT_PPC64_OPT, 0)
+                       Elfwritedynent2(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, dynamic, DT_DEBUG, 0)
+               Elfwritedynent2(ctxt.Arch, dynamic, DT_DEBUG, 0)
        }
 
        if ctxt.IsShared() {
@@ -2391,6 +2391,94 @@ func elfadddynsym(target *Target, syms *ArchSyms, s *sym.Symbol) {
        }
 }
 
+func elfadddynsym2(ldr *loader.Loader, target *Target, syms *ArchSyms, s loader.Sym) {
+       ldr.SetSymDynid(s, int32(Nelfsym))
+       // temporary until wafefront moves past addexport
+       ldr.Syms[s].Dynid = ldr.SymDynid(s)
+       Nelfsym++
+       d := ldr.MakeSymbolUpdater(syms.DynSym2)
+       name := ldr.SymExtname(s)
+       dstru := ldr.MakeSymbolUpdater(syms.DynStr2)
+       st := ldr.SymType(s)
+       cgoeStatic := ldr.AttrCgoExportStatic(s)
+       cgoeDynamic := ldr.AttrCgoExportDynamic(s)
+       cgoexp := (cgoeStatic || cgoeDynamic)
+
+       d.AddUint32(target.Arch, uint32(dstru.Addstring(name)))
+
+       if elf64 {
+
+               /* type */
+               t := STB_GLOBAL << 4
+
+               if cgoexp && st == sym.STEXT {
+                       t |= STT_FUNC
+               } else {
+                       t |= STT_OBJECT
+               }
+               d.AddUint8(uint8(t))
+
+               /* reserved */
+               d.AddUint8(0)
+
+               /* section where symbol is defined */
+               if st == sym.SDYNIMPORT {
+                       d.AddUint16(target.Arch, SHN_UNDEF)
+               } else {
+                       d.AddUint16(target.Arch, 1)
+               }
+
+               /* value */
+               if st == sym.SDYNIMPORT {
+                       d.AddUint64(target.Arch, 0)
+               } else {
+                       d.AddAddrPlus(target.Arch, s, 0)
+               }
+
+               /* size of object */
+               d.AddUint64(target.Arch, uint64(len(ldr.Data(s))))
+
+               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)))
+               }
+       } else {
+
+               /* value */
+               if st == sym.SDYNIMPORT {
+                       d.AddUint32(target.Arch, 0)
+               } else {
+                       d.AddAddrPlus(target.Arch, s, 0)
+               }
+
+               /* size of object */
+               d.AddUint32(target.Arch, uint32(len(ldr.Data(s))))
+
+               /* type */
+               t := STB_GLOBAL << 4
+
+               // TODO(mwhudson): presumably the behavior should actually be the same on both arm and 386.
+               if target.Arch.Family == sys.I386 && cgoexp && st == sym.STEXT {
+                       t |= STT_FUNC
+               } else if target.Arch.Family == sys.ARM && cgoeDynamic && st == sym.STEXT {
+                       t |= STT_FUNC
+               } else {
+                       t |= STT_OBJECT
+               }
+               d.AddUint8(uint8(t))
+               d.AddUint8(0)
+
+               /* shndx */
+               if st == sym.SDYNIMPORT {
+                       d.AddUint16(target.Arch, SHN_UNDEF)
+               } else {
+                       d.AddUint16(target.Arch, 1)
+               }
+       }
+}
+
 func ELF32_R_SYM(info uint32) uint32 {
        return info >> 8
 }
index 55d82655778716d1cd4f315fdf402a2939f2d4e0..575ca6febe4afd6172e074968fb7cb1aea52e952 100644 (file)
@@ -320,16 +320,33 @@ func adddynlib(ctxt *Link, lib string) {
        seenlib[lib] = true
 
        if ctxt.IsELF {
-               s := ctxt.DynStr
-               if s.Size == 0 {
-                       Addstring(s, "")
+               dsu := ctxt.loader.MakeSymbolUpdater(ctxt.DynStr2)
+               if dsu.Size() == 0 {
+                       dsu.Addstring("")
                }
-               elfWriteDynEnt(ctxt.Arch, ctxt.Dynamic, 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 Adddynsym2(ldr *loader.Loader, reporter *ErrorReporter, target *Target, syms *ArchSyms, s loader.Sym) {
+       if ldr.SymDynid(s) >= 0 || target.LinkMode == LinkExternal {
+               return
+       }
+
+       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
@@ -381,17 +398,23 @@ func fieldtrack(arch *sys.Arch, l *loader.Loader) {
 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() {
+               for _, s := range ctxt.Textp2 {
+                       if ctxt.loader.AttrSpecial(s) || ctxt.loader.AttrSubSymbol(s) {
                                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
+                       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)
+                                               // temporary until the wavefront moves past addexport
+                                               ctxt.loader.Syms[rs].Type = sym.SUNDEFEXT
+                                       }
                                }
                        }
                }
@@ -402,12 +425,17 @@ func (ctxt *Link) addexport() {
                return
        }
 
-       for _, exp := range dynexp {
-               Adddynsym(&ctxt.Target, &ctxt.ArchSyms, exp)
+       for _, exp := range ctxt.dynexp2 {
+               Adddynsym2(ctxt.loader, &ctxt.ErrorReporter, &ctxt.Target, &ctxt.ArchSyms, exp)
        }
        for _, lib := range dynlib {
                adddynlib(ctxt, lib)
        }
+
+       // temporary until the wavefront moves past addexport:
+       // copy any changes to loader.Sym symbols back into the sym.Symbol world.
+       modified := []loader.Sym{ctxt.DynSym2, ctxt.Dynamic2, ctxt.DynStr2}
+       ctxt.loader.PropagateLoaderChangesToSymbols(modified, 0)
 }
 
 type Pkg struct {