1
2
3
4
5 package pkginit
6
7 import (
8 "strings"
9
10 "cmd/compile/internal/base"
11 "cmd/compile/internal/ir"
12 "cmd/compile/internal/typecheck"
13 "cmd/compile/internal/types"
14 "cmd/internal/src"
15 )
16
17
18 func instrumentGlobals(fn *ir.Func) *ir.Name {
19 asanGlobalStruct, asanLocationStruct, defStringstruct := createtypes()
20 lname := typecheck.Lookup
21 tconv := typecheck.ConvNop
22
23
24 arraytype := types.NewArray(asanGlobalStruct, int64(len(InstrumentGlobalsMap)))
25 symG := lname(".asanglobals")
26 globals := ir.NewNameAt(base.Pos, symG, arraytype)
27 globals.Class = ir.PEXTERN
28 symG.Def = globals
29 typecheck.Target.Externs = append(typecheck.Target.Externs, globals)
30
31
32 arraytype = types.NewArray(asanLocationStruct, int64(len(InstrumentGlobalsMap)))
33 symL := lname(".asanL")
34 asanlocation := ir.NewNameAt(base.Pos, symL, arraytype)
35 asanlocation.Class = ir.PEXTERN
36 symL.Def = asanlocation
37 typecheck.Target.Externs = append(typecheck.Target.Externs, asanlocation)
38
39
40
41
42
43 symL = lname(".asanName")
44 asanName := ir.NewNameAt(base.Pos, symL, types.Types[types.TSTRING])
45 asanName.Class = ir.PEXTERN
46 symL.Def = asanName
47 typecheck.Target.Externs = append(typecheck.Target.Externs, asanName)
48
49 symL = lname(".asanModulename")
50 asanModulename := ir.NewNameAt(base.Pos, symL, types.Types[types.TSTRING])
51 asanModulename.Class = ir.PEXTERN
52 symL.Def = asanModulename
53 typecheck.Target.Externs = append(typecheck.Target.Externs, asanModulename)
54
55 symL = lname(".asanFilename")
56 asanFilename := ir.NewNameAt(base.Pos, symL, types.Types[types.TSTRING])
57 asanFilename.Class = ir.PEXTERN
58 symL.Def = asanFilename
59 typecheck.Target.Externs = append(typecheck.Target.Externs, asanFilename)
60
61 var init ir.Nodes
62 var c ir.Node
63
64 for i, n := range InstrumentGlobalsSlice {
65 setField := func(f string, val ir.Node, i int) {
66 r := ir.NewAssignStmt(base.Pos, ir.NewSelectorExpr(base.Pos, ir.ODOT,
67 ir.NewIndexExpr(base.Pos, globals, ir.NewInt(base.Pos, int64(i))), lname(f)), val)
68 init.Append(typecheck.Stmt(r))
69 }
70
71 c = tconv(typecheck.NodAddr(n), types.Types[types.TUNSAFEPTR])
72 c = tconv(c, types.Types[types.TUINTPTR])
73 setField("beg", c, i)
74
75 g := n.(*ir.Name)
76 size := g.Type().Size()
77 c = typecheck.DefaultLit(ir.NewInt(base.Pos, size), types.Types[types.TUINTPTR])
78 setField("size", c, i)
79
80 rzSize := GetRedzoneSizeForGlobal(size)
81 sizeWithRz := rzSize + size
82 c = typecheck.DefaultLit(ir.NewInt(base.Pos, sizeWithRz), types.Types[types.TUINTPTR])
83 setField("sizeWithRedzone", c, i)
84
85
86
87
88 name := g.Linksym().Name
89 init.Append(typecheck.Stmt(ir.NewAssignStmt(base.Pos, asanName, ir.NewString(base.Pos, name+"\000"))))
90 c = tconv(typecheck.NodAddr(asanName), types.Types[types.TUNSAFEPTR])
91 c = tconv(c, types.NewPtr(defStringstruct))
92 c = ir.NewSelectorExpr(base.Pos, ir.ODOT, c, lname("data"))
93 setField("name", c, i)
94
95
96
97 init.Append(typecheck.Stmt(ir.NewAssignStmt(base.Pos, asanModulename, ir.NewString(base.Pos, types.LocalPkg.Name+"\000"))))
98 c = tconv(typecheck.NodAddr(asanModulename), types.Types[types.TUNSAFEPTR])
99 c = tconv(c, types.NewPtr(defStringstruct))
100 c = ir.NewSelectorExpr(base.Pos, ir.ODOT, c, lname("data"))
101 setField("moduleName", c, i)
102
103
104 asanLi := ir.NewIndexExpr(base.Pos, asanlocation, ir.NewInt(base.Pos, int64(i)))
105 filename := ir.NewString(base.Pos, base.Ctxt.PosTable.Pos(n.Pos()).Filename()+"\000")
106 init.Append(typecheck.Stmt(ir.NewAssignStmt(base.Pos, asanFilename, filename)))
107 c = tconv(typecheck.NodAddr(asanFilename), types.Types[types.TUNSAFEPTR])
108 c = tconv(c, types.NewPtr(defStringstruct))
109 c = ir.NewSelectorExpr(base.Pos, ir.ODOT, c, lname("data"))
110 init.Append(typecheck.Stmt(ir.NewAssignStmt(base.Pos, ir.NewSelectorExpr(base.Pos, ir.ODOT, asanLi, lname("filename")), c)))
111 line := ir.NewInt(base.Pos, int64(n.Pos().Line()))
112 init.Append(typecheck.Stmt(ir.NewAssignStmt(base.Pos, ir.NewSelectorExpr(base.Pos, ir.ODOT, asanLi, lname("line")), line)))
113 col := ir.NewInt(base.Pos, int64(n.Pos().Col()))
114 init.Append(typecheck.Stmt(ir.NewAssignStmt(base.Pos, ir.NewSelectorExpr(base.Pos, ir.ODOT, asanLi, lname("column")), col)))
115 c = tconv(typecheck.NodAddr(asanLi), types.Types[types.TUNSAFEPTR])
116 c = tconv(c, types.Types[types.TUINTPTR])
117 setField("sourceLocation", c, i)
118 }
119 fn.Body.Append(init...)
120 return globals
121 }
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153 func createtypes() (*types.Type, *types.Type, *types.Type) {
154 up := types.Types[types.TUINTPTR]
155 i32 := types.Types[types.TINT32]
156 fname := typecheck.Lookup
157 nxp := src.NoXPos
158 nfield := types.NewField
159 asanGlobal := types.NewStruct([]*types.Field{
160 nfield(nxp, fname("beg"), up),
161 nfield(nxp, fname("size"), up),
162 nfield(nxp, fname("sizeWithRedzone"), up),
163 nfield(nxp, fname("name"), up),
164 nfield(nxp, fname("moduleName"), up),
165 nfield(nxp, fname("hasDynamicInit"), up),
166 nfield(nxp, fname("sourceLocation"), up),
167 nfield(nxp, fname("odrIndicator"), up),
168 })
169 types.CalcSize(asanGlobal)
170
171 asanLocation := types.NewStruct([]*types.Field{
172 nfield(nxp, fname("filename"), up),
173 nfield(nxp, fname("line"), i32),
174 nfield(nxp, fname("column"), i32),
175 })
176 types.CalcSize(asanLocation)
177
178 defString := types.NewStruct([]*types.Field{
179 types.NewField(nxp, fname("data"), up),
180 types.NewField(nxp, fname("len"), up),
181 })
182 types.CalcSize(defString)
183
184 return asanGlobal, asanLocation, defString
185 }
186
187
188 func GetRedzoneSizeForGlobal(size int64) int64 {
189 maxRZ := int64(1 << 18)
190 minRZ := int64(32)
191 redZone := (size / minRZ / 4) * minRZ
192 switch {
193 case redZone > maxRZ:
194 redZone = maxRZ
195 case redZone < minRZ:
196 redZone = minRZ
197 }
198
199 if size%minRZ != 0 {
200 redZone += minRZ - (size % minRZ)
201 }
202 return redZone
203 }
204
205
206
207
208
209
210
211 var InstrumentGlobalsMap = make(map[string]ir.Node)
212 var InstrumentGlobalsSlice = make([]ir.Node, 0, 0)
213
214 func canInstrumentGlobal(g ir.Node) bool {
215 if g.Op() != ir.ONAME {
216 return false
217 }
218 n := g.(*ir.Name)
219 if n.Class == ir.PFUNC {
220 return false
221 }
222 if n.Sym().Pkg != types.LocalPkg {
223 return false
224 }
225
226 if strings.Contains(n.Sym().Name, "cgo") {
227 return false
228 }
229
230
231 if n.Sym().Linkname != "" {
232 return false
233 }
234
235 return true
236 }
237
View as plain text