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