github.com/bir3/gocompiler@v0.9.2202/src/cmd/link/internal/ld/seh.go (about) 1 // Copyright 2023 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package ld 6 7 import ( 8 "github.com/bir3/gocompiler/src/cmd/internal/sys" 9 "github.com/bir3/gocompiler/src/cmd/link/internal/loader" 10 "github.com/bir3/gocompiler/src/cmd/link/internal/sym" 11 ) 12 13 var sehp struct { 14 pdata []sym.LoaderSym 15 xdata []sym.LoaderSym 16 } 17 18 func writeSEH(ctxt *Link) { 19 switch ctxt.Arch.Family { 20 case sys.AMD64: 21 writeSEHAMD64(ctxt) 22 } 23 } 24 25 func writeSEHAMD64(ctxt *Link) { 26 ldr := ctxt.loader 27 mkSecSym := func(name string, kind sym.SymKind) *loader.SymbolBuilder { 28 s := ldr.CreateSymForUpdate(name, 0) 29 s.SetType(kind) 30 s.SetAlign(4) 31 return s 32 } 33 pdata := mkSecSym(".pdata", sym.SSEHSECT) 34 xdata := mkSecSym(".xdata", sym.SSEHSECT) 35 // The .xdata entries have very low cardinality 36 // as it only contains frame pointer operations, 37 // which are very similar across functions. 38 // These are referenced by .pdata entries using 39 // an RVA, so it is possible, and binary-size wise, 40 // to deduplicate .xdata entries. 41 uwcache := make(map[string]int64) // aux symbol name --> .xdata offset 42 for _, s := range ctxt.Textp { 43 if fi := ldr.FuncInfo(s); !fi.Valid() { 44 continue 45 } 46 uw := ldr.SEHUnwindSym(s) 47 if uw == 0 { 48 continue 49 } 50 name := ctxt.SymName(uw) 51 off, cached := uwcache[name] 52 if !cached { 53 off = xdata.Size() 54 uwcache[name] = off 55 xdata.AddBytes(ldr.Data(uw)) 56 // The SEH unwind data can contain relocations, 57 // make sure those are copied over. 58 rels := ldr.Relocs(uw) 59 for i := 0; i < rels.Count(); i++ { 60 r := rels.At(i) 61 rel, _ := xdata.AddRel(r.Type()) 62 rel.SetOff(int32(off) + r.Off()) 63 rel.SetSiz(r.Siz()) 64 rel.SetSym(r.Sym()) 65 rel.SetAdd(r.Add()) 66 } 67 } 68 69 // Reference: 70 // https://learn.microsoft.com/en-us/cpp/build/exception-handling-x64#struct-runtime_function 71 pdata.AddPEImageRelativeAddrPlus(ctxt.Arch, s, 0) 72 pdata.AddPEImageRelativeAddrPlus(ctxt.Arch, s, ldr.SymSize(s)) 73 pdata.AddPEImageRelativeAddrPlus(ctxt.Arch, xdata.Sym(), off) 74 } 75 sehp.pdata = append(sehp.pdata, pdata.Sym()) 76 sehp.xdata = append(sehp.xdata, xdata.Sym()) 77 }