1
2
3
4
5 package obj
6
7 import (
8 "cmd/internal/objabi"
9 "cmd/internal/src"
10 "fmt"
11 "internal/abi"
12 "strings"
13 )
14
15 type Plist struct {
16 Firstpc *Prog
17 Curfn Func
18 }
19
20
21
22 type ProgAlloc func() *Prog
23
24 func Flushplist(ctxt *Link, plist *Plist, newprog ProgAlloc) {
25 if ctxt.Pkgpath == "" {
26 panic("Flushplist called without Pkgpath")
27 }
28
29
30 var curtext *LSym
31 var etext *Prog
32 var text []*LSym
33
34 var plink *Prog
35 for p := plist.Firstpc; p != nil; p = plink {
36 if ctxt.Debugasm > 0 && ctxt.Debugvlog {
37 fmt.Printf("obj: %v\n", p)
38 }
39 plink = p.Link
40 p.Link = nil
41
42 switch p.As {
43 case AEND:
44 continue
45
46 case ATEXT:
47 s := p.From.Sym
48 if s == nil {
49
50 curtext = nil
51 continue
52 }
53 text = append(text, s)
54 etext = p
55 curtext = s
56 continue
57
58 case AFUNCDATA:
59
60 if curtext == nil {
61 continue
62 }
63 switch p.To.Sym.Name {
64 case "go_args_stackmap":
65 if p.From.Type != TYPE_CONST || p.From.Offset != abi.FUNCDATA_ArgsPointerMaps {
66 ctxt.Diag("%v: FUNCDATA use of go_args_stackmap(SB) without FUNCDATA_ArgsPointerMaps", p)
67 }
68 p.To.Sym = ctxt.LookupDerived(curtext, curtext.Name+".args_stackmap")
69 case "no_pointers_stackmap":
70 if p.From.Type != TYPE_CONST || p.From.Offset != abi.FUNCDATA_LocalsPointerMaps {
71 ctxt.Diag("%v: FUNCDATA use of no_pointers_stackmap(SB) without FUNCDATA_LocalsPointerMaps", p)
72 }
73
74
75
76
77
78 b := make([]byte, 8)
79 ctxt.Arch.ByteOrder.PutUint32(b, 2)
80 s := ctxt.GCLocalsSym(b)
81 if !s.OnList() {
82 ctxt.Globl(s, int64(len(s.P)), int(RODATA|DUPOK))
83 }
84 p.To.Sym = s
85 }
86
87 }
88
89 if curtext == nil {
90 etext = nil
91 continue
92 }
93 etext.Link = p
94 etext = p
95 }
96
97 if newprog == nil {
98 newprog = ctxt.NewProg
99 }
100
101
102 if ctxt.IsAsm {
103 pkgPrefix := objabi.PathToPrefix(ctxt.Pkgpath) + "."
104 for _, s := range text {
105 if !strings.HasPrefix(s.Name, pkgPrefix) {
106 continue
107 }
108
109
110
111
112 if s.ABI() != ABI0 {
113 continue
114 }
115
116
117
118
119
120
121
122 if s.Name == "runtime.addmoduledata" {
123 continue
124 }
125 foundArgMap, foundArgInfo := false, false
126 for p := s.Func().Text; p != nil; p = p.Link {
127 if p.As == AFUNCDATA && p.From.Type == TYPE_CONST {
128 if p.From.Offset == abi.FUNCDATA_ArgsPointerMaps {
129 foundArgMap = true
130 }
131 if p.From.Offset == abi.FUNCDATA_ArgInfo {
132 foundArgInfo = true
133 }
134 if foundArgMap && foundArgInfo {
135 break
136 }
137 }
138 }
139 if !foundArgMap {
140 p := Appendp(s.Func().Text, newprog)
141 p.As = AFUNCDATA
142 p.From.Type = TYPE_CONST
143 p.From.Offset = abi.FUNCDATA_ArgsPointerMaps
144 p.To.Type = TYPE_MEM
145 p.To.Name = NAME_EXTERN
146 p.To.Sym = ctxt.LookupDerived(s, s.Name+".args_stackmap")
147 }
148 if !foundArgInfo {
149 p := Appendp(s.Func().Text, newprog)
150 p.As = AFUNCDATA
151 p.From.Type = TYPE_CONST
152 p.From.Offset = abi.FUNCDATA_ArgInfo
153 p.To.Type = TYPE_MEM
154 p.To.Name = NAME_EXTERN
155 p.To.Sym = ctxt.LookupDerived(s, fmt.Sprintf("%s.arginfo%d", s.Name, s.ABI()))
156 }
157 }
158 }
159
160
161 for _, s := range text {
162 mkfwd(s)
163 if ctxt.Arch.ErrorCheck != nil {
164 ctxt.Arch.ErrorCheck(ctxt, s)
165 }
166 linkpatch(ctxt, s, newprog)
167 ctxt.Arch.Preprocess(ctxt, s, newprog)
168 ctxt.Arch.Assemble(ctxt, s, newprog)
169 if ctxt.Errors > 0 {
170 continue
171 }
172 linkpcln(ctxt, s)
173 ctxt.populateDWARF(plist.Curfn, s)
174 if ctxt.Headtype == objabi.Hwindows && ctxt.Arch.SEH != nil {
175 s.Func().sehUnwindInfoSym = ctxt.Arch.SEH(ctxt, s)
176 }
177 }
178 }
179
180 func (ctxt *Link) InitTextSym(s *LSym, flag int, start src.XPos) {
181 if s == nil {
182
183 return
184 }
185 if s.Func() != nil {
186 otherPos := src.NoPos
187 if s.Func().Text != nil {
188 otherPos = ctxt.PosTable.Pos(s.Func().Text.Pos)
189 }
190 ctxt.Diag("%s: symbol %s redeclared\n\t%s: other declaration of symbol %s", ctxt.PosTable.Pos(start), s.Name, otherPos, s.Name)
191 return
192 }
193 s.NewFuncInfo()
194 if s.OnList() {
195 ctxt.Diag("%s: symbol %s redeclared", ctxt.PosTable.Pos(start), s.Name)
196 return
197 }
198 if strings.HasPrefix(s.Name, `"".`) {
199 ctxt.Diag("%s: unqualified symbol name: %s", ctxt.PosTable.Pos(start), s.Name)
200 }
201
202
203
204
205 _, startLine := ctxt.getFileIndexAndLine(start)
206
207 s.Func().FuncID = objabi.GetFuncID(s.Name, flag&WRAPPER != 0 || flag&ABIWRAPPER != 0)
208 s.Func().FuncFlag = ctxt.toFuncFlag(flag)
209 s.Func().StartLine = startLine
210 s.Set(AttrOnList, true)
211 s.Set(AttrDuplicateOK, flag&DUPOK != 0)
212 s.Set(AttrNoSplit, flag&NOSPLIT != 0)
213 s.Set(AttrReflectMethod, flag&REFLECTMETHOD != 0)
214 s.Set(AttrWrapper, flag&WRAPPER != 0)
215 s.Set(AttrABIWrapper, flag&ABIWRAPPER != 0)
216 s.Set(AttrNeedCtxt, flag&NEEDCTXT != 0)
217 s.Set(AttrNoFrame, flag&NOFRAME != 0)
218 s.Set(AttrPkgInit, flag&PKGINIT != 0)
219 s.Type = objabi.STEXT
220 s.setFIPSType(ctxt)
221 ctxt.Text = append(ctxt.Text, s)
222
223
224 ctxt.dwarfSym(s)
225 }
226
227 func (ctxt *Link) toFuncFlag(flag int) abi.FuncFlag {
228 var out abi.FuncFlag
229 if flag&TOPFRAME != 0 {
230 out |= abi.FuncFlagTopFrame
231 }
232 if ctxt.IsAsm {
233 out |= abi.FuncFlagAsm
234 }
235 return out
236 }
237
238 func (ctxt *Link) Globl(s *LSym, size int64, flag int) {
239 ctxt.GloblPos(s, size, flag, src.NoXPos)
240 }
241 func (ctxt *Link) GloblPos(s *LSym, size int64, flag int, pos src.XPos) {
242 if s.OnList() {
243
244 ctxt.Diag("%s: symbol %s redeclared", ctxt.PosTable.Pos(pos), s.Name)
245 }
246 s.Set(AttrOnList, true)
247 ctxt.Data = append(ctxt.Data, s)
248 s.Size = size
249 if s.Type == 0 {
250 s.Type = objabi.SBSS
251 }
252 if flag&DUPOK != 0 {
253 s.Set(AttrDuplicateOK, true)
254 }
255 if flag&RODATA != 0 {
256 s.Type = objabi.SRODATA
257 } else if flag&NOPTR != 0 {
258 if s.Type.IsDATA() {
259 s.Type = objabi.SNOPTRDATA
260 } else {
261 s.Type = objabi.SNOPTRBSS
262 }
263 } else if flag&TLSBSS != 0 {
264 s.Type = objabi.STLSBSS
265 }
266 s.setFIPSType(ctxt)
267 }
268
269
270
271
272 func (ctxt *Link) EmitEntryLiveness(s *LSym, p *Prog, newprog ProgAlloc) *Prog {
273 pcdata := ctxt.EmitEntryStackMap(s, p, newprog)
274 pcdata = ctxt.EmitEntryUnsafePoint(s, pcdata, newprog)
275 return pcdata
276 }
277
278
279 func (ctxt *Link) EmitEntryStackMap(s *LSym, p *Prog, newprog ProgAlloc) *Prog {
280 pcdata := Appendp(p, newprog)
281 pcdata.Pos = s.Func().Text.Pos
282 pcdata.As = APCDATA
283 pcdata.From.Type = TYPE_CONST
284 pcdata.From.Offset = abi.PCDATA_StackMapIndex
285 pcdata.To.Type = TYPE_CONST
286 pcdata.To.Offset = -1
287
288 return pcdata
289 }
290
291
292 func (ctxt *Link) EmitEntryUnsafePoint(s *LSym, p *Prog, newprog ProgAlloc) *Prog {
293 pcdata := Appendp(p, newprog)
294 pcdata.Pos = s.Func().Text.Pos
295 pcdata.As = APCDATA
296 pcdata.From.Type = TYPE_CONST
297 pcdata.From.Offset = abi.PCDATA_UnsafePoint
298 pcdata.To.Type = TYPE_CONST
299 pcdata.To.Offset = -1
300
301 return pcdata
302 }
303
304
305
306
307
308 func (ctxt *Link) StartUnsafePoint(p *Prog, newprog ProgAlloc) *Prog {
309 pcdata := Appendp(p, newprog)
310 pcdata.As = APCDATA
311 pcdata.From.Type = TYPE_CONST
312 pcdata.From.Offset = abi.PCDATA_UnsafePoint
313 pcdata.To.Type = TYPE_CONST
314 pcdata.To.Offset = abi.UnsafePointUnsafe
315
316 return pcdata
317 }
318
319
320
321
322
323 func (ctxt *Link) EndUnsafePoint(p *Prog, newprog ProgAlloc, oldval int64) *Prog {
324 pcdata := Appendp(p, newprog)
325 pcdata.As = APCDATA
326 pcdata.From.Type = TYPE_CONST
327 pcdata.From.Offset = abi.PCDATA_UnsafePoint
328 pcdata.To.Type = TYPE_CONST
329 pcdata.To.Offset = oldval
330
331 return pcdata
332 }
333
334
335
336
337
338
339
340
341
342
343
344 func MarkUnsafePoints(ctxt *Link, p0 *Prog, newprog ProgAlloc, isUnsafePoint, isRestartable func(*Prog) bool) {
345 if isRestartable == nil {
346
347 isRestartable = func(*Prog) bool { return false }
348 }
349 prev := p0
350 prevPcdata := int64(-1)
351 prevRestart := int64(0)
352 for p := prev.Link; p != nil; p, prev = p.Link, p {
353 if p.As == APCDATA && p.From.Offset == abi.PCDATA_UnsafePoint {
354 prevPcdata = p.To.Offset
355 continue
356 }
357 if prevPcdata == abi.UnsafePointUnsafe {
358 continue
359 }
360 if isUnsafePoint(p) {
361 q := ctxt.StartUnsafePoint(prev, newprog)
362 q.Pc = p.Pc
363 q.Link = p
364
365 for p.Link != nil && isUnsafePoint(p.Link) {
366 p = p.Link
367 }
368 if p.Link == nil {
369 break
370 }
371 p = ctxt.EndUnsafePoint(p, newprog, prevPcdata)
372 p.Pc = p.Link.Pc
373 continue
374 }
375 if isRestartable(p) {
376 val := int64(abi.UnsafePointRestart1)
377 if val == prevRestart {
378 val = abi.UnsafePointRestart2
379 }
380 prevRestart = val
381 q := Appendp(prev, newprog)
382 q.As = APCDATA
383 q.From.Type = TYPE_CONST
384 q.From.Offset = abi.PCDATA_UnsafePoint
385 q.To.Type = TYPE_CONST
386 q.To.Offset = val
387 q.Pc = p.Pc
388 q.Link = p
389
390 if p.Link == nil {
391 break
392 }
393 if isRestartable(p.Link) {
394
395
396 continue
397 }
398 p = Appendp(p, newprog)
399 p.As = APCDATA
400 p.From.Type = TYPE_CONST
401 p.From.Offset = abi.PCDATA_UnsafePoint
402 p.To.Type = TYPE_CONST
403 p.To.Offset = prevPcdata
404 p.Pc = p.Link.Pc
405 }
406 }
407 }
408
View as plain text