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