1
2
3
4
5 package loadpe
6
7 import (
8 "cmd/internal/objabi"
9 "cmd/internal/sys"
10 "cmd/link/internal/loader"
11 "cmd/link/internal/sym"
12 "fmt"
13 "sort"
14 )
15
16 const (
17 UNW_FLAG_EHANDLER = 1 << 3
18 UNW_FLAG_UHANDLER = 2 << 3
19 UNW_FLAG_CHAININFO = 4 << 3
20 unwStaticDataSize = 4
21 unwCodeSize = 2
22 )
23
24
25
26
27 func processSEH(ldr *loader.Loader, arch *sys.Arch, pdata sym.LoaderSym, xdata sym.LoaderSym) error {
28 switch arch.Family {
29 case sys.AMD64:
30 ldr.SetAttrReachable(pdata, true)
31 if xdata != 0 {
32 ldr.SetAttrReachable(xdata, true)
33 }
34 return processSEHAMD64(ldr, pdata)
35 default:
36
37 return fmt.Errorf("unsupported architecture for SEH: %v", arch.Family)
38 }
39 }
40
41 func processSEHAMD64(ldr *loader.Loader, pdata sym.LoaderSym) error {
42
43
44
45
46
47
48
49 rels := ldr.Relocs(pdata)
50 if rels.Count()%3 != 0 {
51 return fmt.Errorf(".pdata symbol %q has invalid relocation count", ldr.SymName(pdata))
52 }
53 for i := 0; i < rels.Count(); i += 3 {
54 xrel := rels.At(i + 2)
55 handler := findHandlerInXDataAMD64(ldr, xrel.Sym(), xrel.Add())
56 if handler != 0 {
57 sb := ldr.MakeSymbolUpdater(rels.At(i).Sym())
58 r, _ := sb.AddRel(objabi.R_KEEP)
59 r.SetSym(handler)
60 }
61 }
62 return nil
63 }
64
65
66
67
68
69 func findHandlerInXDataAMD64(ldr *loader.Loader, xsym sym.LoaderSym, add int64) loader.Sym {
70 data := ldr.Data(xsym)
71 if add < 0 || add+unwStaticDataSize > int64(len(data)) {
72 return 0
73 }
74 data = data[add:]
75 var isChained bool
76 switch flag := data[0]; {
77 case flag&UNW_FLAG_EHANDLER != 0 || flag&UNW_FLAG_UHANDLER != 0:
78
79 case flag&UNW_FLAG_CHAININFO != 0:
80 isChained = true
81 default:
82
83 return 0
84 }
85 codes := data[2]
86 if codes%2 != 0 {
87
88 codes += 1
89 }
90
91
92 targetOff := add + unwStaticDataSize + unwCodeSize*int64(codes)
93 xrels := ldr.Relocs(xsym)
94 xrelsCount := xrels.Count()
95 idx := sort.Search(xrelsCount, func(i int) bool {
96 return int64(xrels.At(i).Off()) >= targetOff
97 })
98 if idx == xrelsCount {
99 return 0
100 }
101 if isChained {
102
103 idx += 2
104 if idx >= xrelsCount {
105 return 0
106 }
107 r := xrels.At(idx)
108 return findHandlerInXDataAMD64(ldr, r.Sym(), r.Add())
109 }
110 return xrels.At(idx).Sym()
111 }
112
View as plain text