]> Cypherpunks.ru repositories - gostls13.git/blob - 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
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         "cmd/internal/sys"
9         "cmd/link/internal/loader"
10         "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 }