]> Cypherpunks.ru repositories - gostls13.git/blobdiff - src/cmd/link/internal/ld/seh.go
cmd/internal/link: merge .pdata and .xdata sections from host object files
[gostls13.git] / src / cmd / link / internal / ld / seh.go
index b95084751ccf5d5a1d052775112c6ff216743b03..9f0f747c042b154a337e2eaecf4df58823213f2f 100644 (file)
@@ -11,7 +11,8 @@ import (
 )
 
 var sehp struct {
-       pdata loader.Sym
+       pdata []sym.LoaderSym
+       xdata []sym.LoaderSym
 }
 
 func writeSEH(ctxt *Link) {
@@ -29,26 +30,48 @@ func writeSEHAMD64(ctxt *Link) {
                s.SetAlign(4)
                return s
        }
-       pdata := mkSecSym(".pdata", sym.SPDATASECT)
-       // TODO: the following 12 bytes represent a dummy unwind info,
-       // remove once unwind infos are encoded in the .xdata section.
-       pdata.AddUint64(ctxt.Arch, 0)
-       pdata.AddUint32(ctxt.Arch, 0)
+       pdata := mkSecSym(".pdata", sym.SSEHSECT)
+       xdata := mkSecSym(".xdata", sym.SSEHSECT)
+       // The .xdata entries have very low cardinality
+       // as it only contains frame pointer operations,
+       // which are very similar across functions.
+       // These are referenced by .pdata entries using
+       // an RVA, so it is possible, and binary-size wise,
+       // to deduplicate .xdata entries.
+       uwcache := make(map[string]int64) // aux symbol name --> .xdata offset
        for _, s := range ctxt.Textp {
-               if fi := ldr.FuncInfo(s); !fi.Valid() || fi.TopFrame() {
+               if fi := ldr.FuncInfo(s); !fi.Valid() {
                        continue
                }
                uw := ldr.SEHUnwindSym(s)
                if uw == 0 {
                        continue
                }
+               name := ctxt.SymName(uw)
+               off, cached := uwcache[name]
+               if !cached {
+                       off = xdata.Size()
+                       uwcache[name] = off
+                       xdata.AddBytes(ldr.Data(uw))
+                       // The SEH unwind data can contain relocations,
+                       // make sure those are copied over.
+                       rels := ldr.Relocs(uw)
+                       for i := 0; i < rels.Count(); i++ {
+                               r := rels.At(i)
+                               rel, _ := xdata.AddRel(r.Type())
+                               rel.SetOff(int32(off) + r.Off())
+                               rel.SetSiz(r.Siz())
+                               rel.SetSym(r.Sym())
+                               rel.SetAdd(r.Add())
+                       }
+               }
 
                // Reference:
                // https://learn.microsoft.com/en-us/cpp/build/exception-handling-x64#struct-runtime_function
                pdata.AddPEImageRelativeAddrPlus(ctxt.Arch, s, 0)
                pdata.AddPEImageRelativeAddrPlus(ctxt.Arch, s, ldr.SymSize(s))
-               // TODO: reference the .xdata symbol.
-               pdata.AddPEImageRelativeAddrPlus(ctxt.Arch, pdata.Sym(), 0)
+               pdata.AddPEImageRelativeAddrPlus(ctxt.Arch, xdata.Sym(), off)
        }
-       sehp.pdata = pdata.Sym()
+       sehp.pdata = append(sehp.pdata, pdata.Sym())
+       sehp.xdata = append(sehp.xdata, xdata.Sym())
 }