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