1
2
3
4
5 package ld
6
7 import (
8 "cmd/internal/sys"
9 "cmd/link/internal/loader"
10 "cmd/link/internal/sym"
11 "cmp"
12 "slices"
13 )
14
15 var sehp struct {
16 pdata []sym.LoaderSym
17 xdata []sym.LoaderSym
18 }
19
20
21
22 func collectSEH(ctxt *Link) {
23 switch ctxt.Arch.Family {
24 case sys.AMD64:
25 collectSEHAMD64(ctxt)
26 }
27 }
28
29 func collectSEHAMD64(ctxt *Link) {
30 ldr := ctxt.loader
31 mkSecSym := func(name string, kind sym.SymKind) *loader.SymbolBuilder {
32 s := ldr.CreateSymForUpdate(name, 0)
33 s.SetType(kind)
34 s.SetAlign(4)
35 return s
36 }
37 pdata := mkSecSym(".pdata", sym.SSEHSECT)
38 xdata := mkSecSym(".xdata", sym.SSEHSECT)
39
40
41
42
43
44
45 uwcache := make(map[string]int64)
46 type pdataEntry struct {
47 start sym.LoaderSym
48 xdataOff int64
49 }
50 var entries []pdataEntry
51 for _, s := range ctxt.Textp {
52 if fi := ldr.FuncInfo(s); !fi.Valid() {
53 continue
54 }
55 uw := ldr.SEHUnwindSym(s)
56 if uw == 0 {
57 continue
58 }
59 name := ctxt.SymName(uw)
60 off, cached := uwcache[name]
61 if !cached {
62 off = xdata.Size()
63 uwcache[name] = off
64 xdata.AddBytes(ldr.Data(uw))
65
66
67 rels := ldr.Relocs(uw)
68 for i := 0; i < rels.Count(); i++ {
69 r := rels.At(i)
70 rel, _ := xdata.AddRel(r.Type())
71 rel.SetOff(int32(off) + r.Off())
72 rel.SetSiz(r.Siz())
73 rel.SetSym(r.Sym())
74 rel.SetAdd(r.Add())
75 }
76 }
77
78 entries = append(entries, pdataEntry{start: s, xdataOff: off})
79 }
80 slices.SortFunc(entries, func(a, b pdataEntry) int {
81 return cmp.Compare(ldr.SymAddr(a.start), ldr.SymAddr(b.start))
82 })
83 for _, ent := range entries {
84
85
86 pdata.AddPEImageRelativeAddrPlus(ctxt.Arch, ent.start, 0)
87 pdata.AddPEImageRelativeAddrPlus(ctxt.Arch, ent.start, ldr.SymSize(ent.start))
88 pdata.AddPEImageRelativeAddrPlus(ctxt.Arch, xdata.Sym(), ent.xdataOff)
89 }
90 if pdata.Size() > 0 {
91 sehp.pdata = append(sehp.pdata, pdata.Sym())
92 }
93 if xdata.Size() > 0 {
94 sehp.xdata = append(sehp.xdata, xdata.Sym())
95 }
96 }
97
View as plain text