1
2
3
4
5 package dwarfgen
6
7 import (
8 "bytes"
9 "flag"
10 "fmt"
11 "internal/buildcfg"
12 "sort"
13
14 "cmd/compile/internal/base"
15 "cmd/compile/internal/ir"
16 "cmd/compile/internal/reflectdata"
17 "cmd/compile/internal/ssa"
18 "cmd/compile/internal/ssagen"
19 "cmd/compile/internal/types"
20 "cmd/internal/dwarf"
21 "cmd/internal/obj"
22 "cmd/internal/objabi"
23 "cmd/internal/src"
24 )
25
26 func Info(fnsym *obj.LSym, infosym *obj.LSym, curfn interface{}) ([]dwarf.Scope, dwarf.InlCalls) {
27 fn := curfn.(*ir.Func)
28
29 if fn.Nname != nil {
30 expect := fn.Linksym()
31 if fnsym.ABI() == obj.ABI0 {
32 expect = fn.LinksymABI(obj.ABI0)
33 }
34 if fnsym != expect {
35 base.Fatalf("unexpected fnsym: %v != %v", fnsym, expect)
36 }
37 }
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71 isODCLFUNC := infosym.Name == ""
72
73 var apdecls []*ir.Name
74
75 if isODCLFUNC {
76 for _, n := range fn.Dcl {
77 if n.Op() != ir.ONAME {
78 continue
79 }
80 switch n.Class {
81 case ir.PAUTO:
82 if !n.Used() {
83
84 if fnsym.Func().Text != nil {
85 base.Fatalf("debuginfo unused node (AllocFrame should truncate fn.Func.Dcl)")
86 }
87 continue
88 }
89 case ir.PPARAM, ir.PPARAMOUT:
90 default:
91 continue
92 }
93 apdecls = append(apdecls, n)
94 fnsym.Func().RecordAutoType(reflectdata.TypeLinksym(n.Type()))
95 }
96 }
97
98 decls, dwarfVars := createDwarfVars(fnsym, isODCLFUNC, fn, apdecls)
99
100
101
102
103
104 typesyms := []*obj.LSym{}
105 for t, _ := range fnsym.Func().Autot {
106 typesyms = append(typesyms, t)
107 }
108 sort.Sort(obj.BySymName(typesyms))
109 for _, sym := range typesyms {
110 r := obj.Addrel(infosym)
111 r.Sym = sym
112 r.Type = objabi.R_USETYPE
113 }
114 fnsym.Func().Autot = nil
115
116 var varScopes []ir.ScopeID
117 for _, decl := range decls {
118 pos := declPos(decl)
119 varScopes = append(varScopes, findScope(fn.Marks, pos))
120 }
121
122 scopes := assembleScopes(fnsym, fn, dwarfVars, varScopes)
123 var inlcalls dwarf.InlCalls
124 if base.Flag.GenDwarfInl > 0 {
125 inlcalls = assembleInlines(fnsym, dwarfVars)
126 }
127 return scopes, inlcalls
128 }
129
130 func declPos(decl *ir.Name) src.XPos {
131 return decl.Canonical().Pos()
132 }
133
134
135
136 func createDwarfVars(fnsym *obj.LSym, complexOK bool, fn *ir.Func, apDecls []*ir.Name) ([]*ir.Name, []*dwarf.Var) {
137
138 var vars []*dwarf.Var
139 var decls []*ir.Name
140 var selected ir.NameSet
141
142 if base.Ctxt.Flag_locationlists && base.Ctxt.Flag_optimize && fn.DebugInfo != nil && complexOK {
143 decls, vars, selected = createComplexVars(fnsym, fn)
144 } else if fn.ABI == obj.ABIInternal && base.Flag.N != 0 && complexOK {
145 decls, vars, selected = createABIVars(fnsym, fn, apDecls)
146 } else {
147 decls, vars, selected = createSimpleVars(fnsym, apDecls)
148 }
149
150 dcl := apDecls
151 if fnsym.WasInlined() {
152 dcl = preInliningDcls(fnsym)
153 }
154
155
156
157
158
159
160
161
162
163
164
165
166
167 for _, n := range dcl {
168 if selected.Has(n) {
169 continue
170 }
171 c := n.Sym().Name[0]
172 if c == '.' || n.Type().IsUntyped() {
173 continue
174 }
175 if n.Class == ir.PPARAM && !ssagen.TypeOK(n.Type()) {
176
177
178
179
180
181
182
183 vars = append(vars, createSimpleVar(fnsym, n))
184 decls = append(decls, n)
185 continue
186 }
187 typename := dwarf.InfoPrefix + types.TypeSymName(n.Type())
188 decls = append(decls, n)
189 abbrev := dwarf.DW_ABRV_AUTO_LOCLIST
190 isReturnValue := (n.Class == ir.PPARAMOUT)
191 if n.Class == ir.PPARAM || n.Class == ir.PPARAMOUT {
192 abbrev = dwarf.DW_ABRV_PARAM_LOCLIST
193 }
194 if n.Esc() == ir.EscHeap {
195
196
197
198 }
199 inlIndex := 0
200 if base.Flag.GenDwarfInl > 1 {
201 if n.InlFormal() || n.InlLocal() {
202 inlIndex = posInlIndex(n.Pos()) + 1
203 if n.InlFormal() {
204 abbrev = dwarf.DW_ABRV_PARAM_LOCLIST
205 }
206 }
207 }
208 declpos := base.Ctxt.InnermostPos(n.Pos())
209 vars = append(vars, &dwarf.Var{
210 Name: n.Sym().Name,
211 IsReturnValue: isReturnValue,
212 Abbrev: abbrev,
213 StackOffset: int32(n.FrameOffset()),
214 Type: base.Ctxt.Lookup(typename),
215 DeclFile: declpos.RelFilename(),
216 DeclLine: declpos.RelLine(),
217 DeclCol: declpos.Col(),
218 InlIndex: int32(inlIndex),
219 ChildIndex: -1,
220 })
221
222 fnsym.Func().RecordAutoType(reflectdata.TypeLinksym(n.Type()))
223 }
224
225
226 sortDeclsAndVars(fn, decls, vars)
227
228 return decls, vars
229 }
230
231
232
233
234
235
236
237 func sortDeclsAndVars(fn *ir.Func, decls []*ir.Name, vars []*dwarf.Var) {
238 paramOrder := make(map[*ir.Name]int)
239 idx := 1
240 for _, selfn := range types.RecvsParamsResults {
241 fsl := selfn(fn.Type()).FieldSlice()
242 for _, f := range fsl {
243 if n, ok := f.Nname.(*ir.Name); ok {
244 paramOrder[n] = idx
245 idx++
246 }
247 }
248 }
249 sort.Stable(varsAndDecls{decls, vars, paramOrder})
250 }
251
252 type varsAndDecls struct {
253 decls []*ir.Name
254 vars []*dwarf.Var
255 paramOrder map[*ir.Name]int
256 }
257
258 func (v varsAndDecls) Len() int {
259 return len(v.decls)
260 }
261
262 func (v varsAndDecls) Less(i, j int) bool {
263 nameLT := func(ni, nj *ir.Name) bool {
264 oi, foundi := v.paramOrder[ni]
265 oj, foundj := v.paramOrder[nj]
266 if foundi {
267 if foundj {
268 return oi < oj
269 } else {
270 return true
271 }
272 }
273 return false
274 }
275 return nameLT(v.decls[i], v.decls[j])
276 }
277
278 func (v varsAndDecls) Swap(i, j int) {
279 v.vars[i], v.vars[j] = v.vars[j], v.vars[i]
280 v.decls[i], v.decls[j] = v.decls[j], v.decls[i]
281 }
282
283
284
285
286
287
288
289 func preInliningDcls(fnsym *obj.LSym) []*ir.Name {
290 fn := base.Ctxt.DwFixups.GetPrecursorFunc(fnsym).(*ir.Func)
291 var rdcl []*ir.Name
292 for _, n := range fn.Inl.Dcl {
293 c := n.Sym().Name[0]
294
295
296 if unversion(n.Sym().Name) == "_" || c == '.' || n.Type().IsUntyped() {
297 continue
298 }
299 rdcl = append(rdcl, n)
300 }
301 return rdcl
302 }
303
304
305
306 func createSimpleVars(fnsym *obj.LSym, apDecls []*ir.Name) ([]*ir.Name, []*dwarf.Var, ir.NameSet) {
307 var vars []*dwarf.Var
308 var decls []*ir.Name
309 var selected ir.NameSet
310 for _, n := range apDecls {
311 if ir.IsAutoTmp(n) {
312 continue
313 }
314
315 decls = append(decls, n)
316 vars = append(vars, createSimpleVar(fnsym, n))
317 selected.Add(n)
318 }
319 return decls, vars, selected
320 }
321
322 func createSimpleVar(fnsym *obj.LSym, n *ir.Name) *dwarf.Var {
323 var abbrev int
324 var offs int64
325
326 localAutoOffset := func() int64 {
327 offs = n.FrameOffset()
328 if base.Ctxt.FixedFrameSize() == 0 {
329 offs -= int64(types.PtrSize)
330 }
331 if buildcfg.FramePointerEnabled {
332 offs -= int64(types.PtrSize)
333 }
334 return offs
335 }
336
337 switch n.Class {
338 case ir.PAUTO:
339 offs = localAutoOffset()
340 abbrev = dwarf.DW_ABRV_AUTO
341 case ir.PPARAM, ir.PPARAMOUT:
342 abbrev = dwarf.DW_ABRV_PARAM
343 if n.IsOutputParamInRegisters() {
344 offs = localAutoOffset()
345 } else {
346 offs = n.FrameOffset() + base.Ctxt.FixedFrameSize()
347 }
348
349 default:
350 base.Fatalf("createSimpleVar unexpected class %v for node %v", n.Class, n)
351 }
352
353 typename := dwarf.InfoPrefix + types.TypeSymName(n.Type())
354 delete(fnsym.Func().Autot, reflectdata.TypeLinksym(n.Type()))
355 inlIndex := 0
356 if base.Flag.GenDwarfInl > 1 {
357 if n.InlFormal() || n.InlLocal() {
358 inlIndex = posInlIndex(n.Pos()) + 1
359 if n.InlFormal() {
360 abbrev = dwarf.DW_ABRV_PARAM
361 }
362 }
363 }
364 declpos := base.Ctxt.InnermostPos(declPos(n))
365 return &dwarf.Var{
366 Name: n.Sym().Name,
367 IsReturnValue: n.Class == ir.PPARAMOUT,
368 IsInlFormal: n.InlFormal(),
369 Abbrev: abbrev,
370 StackOffset: int32(offs),
371 Type: base.Ctxt.Lookup(typename),
372 DeclFile: declpos.RelFilename(),
373 DeclLine: declpos.RelLine(),
374 DeclCol: declpos.Col(),
375 InlIndex: int32(inlIndex),
376 ChildIndex: -1,
377 }
378 }
379
380
381
382
383
384
385 func createABIVars(fnsym *obj.LSym, fn *ir.Func, apDecls []*ir.Name) ([]*ir.Name, []*dwarf.Var, ir.NameSet) {
386
387
388
389 decls, vars, selected := createComplexVars(fnsym, fn)
390
391
392
393
394 for _, n := range apDecls {
395 if ir.IsAutoTmp(n) {
396 continue
397 }
398 if _, ok := selected[n]; ok {
399
400 continue
401 }
402
403 decls = append(decls, n)
404 vars = append(vars, createSimpleVar(fnsym, n))
405 selected.Add(n)
406 }
407
408 return decls, vars, selected
409 }
410
411
412
413 func createComplexVars(fnsym *obj.LSym, fn *ir.Func) ([]*ir.Name, []*dwarf.Var, ir.NameSet) {
414 debugInfo := fn.DebugInfo.(*ssa.FuncDebug)
415
416
417 var decls []*ir.Name
418 var vars []*dwarf.Var
419 var ssaVars ir.NameSet
420
421 for varID, dvar := range debugInfo.Vars {
422 n := dvar
423 ssaVars.Add(n)
424 for _, slot := range debugInfo.VarSlots[varID] {
425 ssaVars.Add(debugInfo.Slots[slot].N)
426 }
427
428 if dvar := createComplexVar(fnsym, fn, ssa.VarID(varID)); dvar != nil {
429 decls = append(decls, n)
430 vars = append(vars, dvar)
431 }
432 }
433
434 return decls, vars, ssaVars
435 }
436
437
438 func createComplexVar(fnsym *obj.LSym, fn *ir.Func, varID ssa.VarID) *dwarf.Var {
439 debug := fn.DebugInfo.(*ssa.FuncDebug)
440 n := debug.Vars[varID]
441
442 var abbrev int
443 switch n.Class {
444 case ir.PAUTO:
445 abbrev = dwarf.DW_ABRV_AUTO_LOCLIST
446 case ir.PPARAM, ir.PPARAMOUT:
447 abbrev = dwarf.DW_ABRV_PARAM_LOCLIST
448 default:
449 return nil
450 }
451
452 gotype := reflectdata.TypeLinksym(n.Type())
453 delete(fnsym.Func().Autot, gotype)
454 typename := dwarf.InfoPrefix + gotype.Name[len("type."):]
455 inlIndex := 0
456 if base.Flag.GenDwarfInl > 1 {
457 if n.InlFormal() || n.InlLocal() {
458 inlIndex = posInlIndex(n.Pos()) + 1
459 if n.InlFormal() {
460 abbrev = dwarf.DW_ABRV_PARAM_LOCLIST
461 }
462 }
463 }
464 declpos := base.Ctxt.InnermostPos(n.Pos())
465 dvar := &dwarf.Var{
466 Name: n.Sym().Name,
467 IsReturnValue: n.Class == ir.PPARAMOUT,
468 IsInlFormal: n.InlFormal(),
469 Abbrev: abbrev,
470 Type: base.Ctxt.Lookup(typename),
471
472
473
474
475 StackOffset: ssagen.StackOffset(debug.Slots[debug.VarSlots[varID][0]]),
476 DeclFile: declpos.RelFilename(),
477 DeclLine: declpos.RelLine(),
478 DeclCol: declpos.Col(),
479 InlIndex: int32(inlIndex),
480 ChildIndex: -1,
481 }
482 list := debug.LocationLists[varID]
483 if len(list) != 0 {
484 dvar.PutLocationList = func(listSym, startPC dwarf.Sym) {
485 debug.PutLocationList(list, base.Ctxt, listSym.(*obj.LSym), startPC.(*obj.LSym))
486 }
487 }
488 return dvar
489 }
490
491
492
493 func RecordFlags(flags ...string) {
494 if base.Ctxt.Pkgpath == "" {
495
496
497 return
498 }
499
500 type BoolFlag interface {
501 IsBoolFlag() bool
502 }
503 type CountFlag interface {
504 IsCountFlag() bool
505 }
506 var cmd bytes.Buffer
507 for _, name := range flags {
508 f := flag.Lookup(name)
509 if f == nil {
510 continue
511 }
512 getter := f.Value.(flag.Getter)
513 if getter.String() == f.DefValue {
514
515 continue
516 }
517 if bf, ok := f.Value.(BoolFlag); ok && bf.IsBoolFlag() {
518 val, ok := getter.Get().(bool)
519 if ok && val {
520 fmt.Fprintf(&cmd, " -%s", f.Name)
521 continue
522 }
523 }
524 if cf, ok := f.Value.(CountFlag); ok && cf.IsCountFlag() {
525 val, ok := getter.Get().(int)
526 if ok && val == 1 {
527 fmt.Fprintf(&cmd, " -%s", f.Name)
528 continue
529 }
530 }
531 fmt.Fprintf(&cmd, " -%s=%v", f.Name, getter.Get())
532 }
533
534
535
536
537
538 if buildcfg.Experiment.RegabiArgs {
539 cmd.Write([]byte(" regabi"))
540 }
541
542 if cmd.Len() == 0 {
543 return
544 }
545 s := base.Ctxt.Lookup(dwarf.CUInfoPrefix + "producer." + base.Ctxt.Pkgpath)
546 s.Type = objabi.SDWARFCUINFO
547
548
549 s.Set(obj.AttrDuplicateOK, true)
550 base.Ctxt.Data = append(base.Ctxt.Data, s)
551 s.P = cmd.Bytes()[1:]
552 }
553
554
555
556 func RecordPackageName() {
557 s := base.Ctxt.Lookup(dwarf.CUInfoPrefix + "packagename." + base.Ctxt.Pkgpath)
558 s.Type = objabi.SDWARFCUINFO
559
560
561 s.Set(obj.AttrDuplicateOK, true)
562 base.Ctxt.Data = append(base.Ctxt.Data, s)
563 s.P = []byte(types.LocalPkg.Name)
564 }
565
View as plain text