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("%s: FUNCDATA use of go_args_stackmap(SB) without FUNCDATA_ArgsPointerMaps", p.Pos)
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("%s: FUNCDATA use of no_pointers_stackmap(SB) without FUNCDATA_LocalsPointerMaps", p.Pos)
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 ctxt.Diag("%s: symbol %s redeclared\n\t%s: other declaration of symbol %s", ctxt.PosTable.Pos(start), s.Name, ctxt.PosTable.Pos(s.Func().Text.Pos), s.Name)
187 return
188 }
189 s.NewFuncInfo()
190 if s.OnList() {
191 ctxt.Diag("%s: symbol %s redeclared", ctxt.PosTable.Pos(start), s.Name)
192 return
193 }
194 if strings.HasPrefix(s.Name, `"".`) {
195 ctxt.Diag("%s: unqualified symbol name: %s", ctxt.PosTable.Pos(start), s.Name)
196 }
197
198
199
200
201 _, startLine := ctxt.getFileIndexAndLine(start)
202
203 s.Func().FuncID = objabi.GetFuncID(s.Name, flag&WRAPPER != 0 || flag&ABIWRAPPER != 0)
204 s.Func().FuncFlag = ctxt.toFuncFlag(flag)
205 s.Func().StartLine = startLine
206 s.Set(AttrOnList, true)
207 s.Set(AttrDuplicateOK, flag&DUPOK != 0)
208 s.Set(AttrNoSplit, flag&NOSPLIT != 0)
209 s.Set(AttrReflectMethod, flag&REFLECTMETHOD != 0)
210 s.Set(AttrWrapper, flag&WRAPPER != 0)
211 s.Set(AttrABIWrapper, flag&ABIWRAPPER != 0)
212 s.Set(AttrNeedCtxt, flag&NEEDCTXT != 0)
213 s.Set(AttrNoFrame, flag&NOFRAME != 0)
214 s.Set(AttrPkgInit, flag&PKGINIT != 0)
215 s.Type = objabi.STEXT
216 ctxt.Text = append(ctxt.Text, s)
217
218
219 ctxt.dwarfSym(s)
220 }
221
222 func (ctxt *Link) toFuncFlag(flag int) abi.FuncFlag {
223 var out abi.FuncFlag
224 if flag&TOPFRAME != 0 {
225 out |= abi.FuncFlagTopFrame
226 }
227 if ctxt.IsAsm {
228 out |= abi.FuncFlagAsm
229 }
230 return out
231 }
232
233 func (ctxt *Link) Globl(s *LSym, size int64, flag int) {
234 ctxt.GloblPos(s, size, flag, src.NoXPos)
235 }
236 func (ctxt *Link) GloblPos(s *LSym, size int64, flag int, pos src.XPos) {
237 if s.OnList() {
238
239 ctxt.Diag("%s: symbol %s redeclared", ctxt.PosTable.Pos(pos), s.Name)
240 }
241 s.Set(AttrOnList, true)
242 ctxt.Data = append(ctxt.Data, s)
243 s.Size = size
244 if s.Type == 0 {
245 s.Type = objabi.SBSS
246 }
247 if flag&DUPOK != 0 {
248 s.Set(AttrDuplicateOK, true)
249 }
250 if flag&RODATA != 0 {
251 s.Type = objabi.SRODATA
252 } else if flag&NOPTR != 0 {
253 if s.Type == objabi.SDATA {
254 s.Type = objabi.SNOPTRDATA
255 } else {
256 s.Type = objabi.SNOPTRBSS
257 }
258 } else if flag&TLSBSS != 0 {
259 s.Type = objabi.STLSBSS
260 }
261 }
262
263
264
265
266 func (ctxt *Link) EmitEntryLiveness(s *LSym, p *Prog, newprog ProgAlloc) *Prog {
267 pcdata := ctxt.EmitEntryStackMap(s, p, newprog)
268 pcdata = ctxt.EmitEntryUnsafePoint(s, pcdata, newprog)
269 return pcdata
270 }
271
272
273 func (ctxt *Link) EmitEntryStackMap(s *LSym, p *Prog, newprog ProgAlloc) *Prog {
274 pcdata := Appendp(p, newprog)
275 pcdata.Pos = s.Func().Text.Pos
276 pcdata.As = APCDATA
277 pcdata.From.Type = TYPE_CONST
278 pcdata.From.Offset = abi.PCDATA_StackMapIndex
279 pcdata.To.Type = TYPE_CONST
280 pcdata.To.Offset = -1
281
282 return pcdata
283 }
284
285
286 func (ctxt *Link) EmitEntryUnsafePoint(s *LSym, p *Prog, newprog ProgAlloc) *Prog {
287 pcdata := Appendp(p, newprog)
288 pcdata.Pos = s.Func().Text.Pos
289 pcdata.As = APCDATA
290 pcdata.From.Type = TYPE_CONST
291 pcdata.From.Offset = abi.PCDATA_UnsafePoint
292 pcdata.To.Type = TYPE_CONST
293 pcdata.To.Offset = -1
294
295 return pcdata
296 }
297
298
299
300
301
302 func (ctxt *Link) StartUnsafePoint(p *Prog, newprog ProgAlloc) *Prog {
303 pcdata := Appendp(p, newprog)
304 pcdata.As = APCDATA
305 pcdata.From.Type = TYPE_CONST
306 pcdata.From.Offset = abi.PCDATA_UnsafePoint
307 pcdata.To.Type = TYPE_CONST
308 pcdata.To.Offset = abi.UnsafePointUnsafe
309
310 return pcdata
311 }
312
313
314
315
316
317 func (ctxt *Link) EndUnsafePoint(p *Prog, newprog ProgAlloc, oldval int64) *Prog {
318 pcdata := Appendp(p, newprog)
319 pcdata.As = APCDATA
320 pcdata.From.Type = TYPE_CONST
321 pcdata.From.Offset = abi.PCDATA_UnsafePoint
322 pcdata.To.Type = TYPE_CONST
323 pcdata.To.Offset = oldval
324
325 return pcdata
326 }
327
328
329
330
331
332
333
334
335
336
337
338 func MarkUnsafePoints(ctxt *Link, p0 *Prog, newprog ProgAlloc, isUnsafePoint, isRestartable func(*Prog) bool) {
339 if isRestartable == nil {
340
341 isRestartable = func(*Prog) bool { return false }
342 }
343 prev := p0
344 prevPcdata := int64(-1)
345 prevRestart := int64(0)
346 for p := prev.Link; p != nil; p, prev = p.Link, p {
347 if p.As == APCDATA && p.From.Offset == abi.PCDATA_UnsafePoint {
348 prevPcdata = p.To.Offset
349 continue
350 }
351 if prevPcdata == abi.UnsafePointUnsafe {
352 continue
353 }
354 if isUnsafePoint(p) {
355 q := ctxt.StartUnsafePoint(prev, newprog)
356 q.Pc = p.Pc
357 q.Link = p
358
359 for p.Link != nil && isUnsafePoint(p.Link) {
360 p = p.Link
361 }
362 if p.Link == nil {
363 break
364 }
365 p = ctxt.EndUnsafePoint(p, newprog, prevPcdata)
366 p.Pc = p.Link.Pc
367 continue
368 }
369 if isRestartable(p) {
370 val := int64(abi.UnsafePointRestart1)
371 if val == prevRestart {
372 val = abi.UnsafePointRestart2
373 }
374 prevRestart = val
375 q := Appendp(prev, newprog)
376 q.As = APCDATA
377 q.From.Type = TYPE_CONST
378 q.From.Offset = abi.PCDATA_UnsafePoint
379 q.To.Type = TYPE_CONST
380 q.To.Offset = val
381 q.Pc = p.Pc
382 q.Link = p
383
384 if p.Link == nil {
385 break
386 }
387 if isRestartable(p.Link) {
388
389
390 continue
391 }
392 p = Appendp(p, newprog)
393 p.As = APCDATA
394 p.From.Type = TYPE_CONST
395 p.From.Offset = abi.PCDATA_UnsafePoint
396 p.To.Type = TYPE_CONST
397 p.To.Offset = prevPcdata
398 p.Pc = p.Link.Pc
399 }
400 }
401 }
402
View as plain text