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