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.
9 "cmd/link/internal/loader"
10 "cmd/link/internal/sym"
18 func writeSEH(ctxt *Link) {
19 switch ctxt.Arch.Family {
25 func writeSEHAMD64(ctxt *Link) {
27 mkSecSym := func(name string, kind sym.SymKind) *loader.SymbolBuilder {
28 s := ldr.CreateSymForUpdate(name, 0)
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() {
46 uw := ldr.SEHUnwindSym(s)
50 name := ctxt.SymName(uw)
51 off, cached := uwcache[name]
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++ {
61 rel, _ := xdata.AddRel(r.Type())
62 rel.SetOff(int32(off) + r.Off())
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)
75 sehp.pdata = append(sehp.pdata, pdata.Sym())
76 sehp.xdata = append(sehp.xdata, xdata.Sym())