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 } else {
154
155
156
157
158
159 debugInfo := fn.DebugInfo.(*ssa.FuncDebug)
160 for _, n := range debugInfo.RegOutputParams {
161 if n.Class != ir.PPARAMOUT || !n.IsOutputParamInRegisters() {
162 panic("invalid ir.Name on debugInfo.RegOutputParams list")
163 }
164 dcl = append(dcl, n)
165 }
166 }
167
168
169
170
171
172
173
174
175
176
177
178
179
180 for _, n := range dcl {
181 if selected.Has(n) {
182 continue
183 }
184 c := n.Sym().Name[0]
185 if c == '.' || n.Type().IsUntyped() {
186 continue
187 }
188 if n.Class == ir.PPARAM && !ssagen.TypeOK(n.Type()) {
189
190
191
192
193
194
195
196 vars = append(vars, createSimpleVar(fnsym, n))
197 decls = append(decls, n)
198 continue
199 }
200 typename := dwarf.InfoPrefix + types.TypeSymName(n.Type())
201 decls = append(decls, n)
202 abbrev := dwarf.DW_ABRV_AUTO_LOCLIST
203 isReturnValue := (n.Class == ir.PPARAMOUT)
204 if n.Class == ir.PPARAM || n.Class == ir.PPARAMOUT {
205 abbrev = dwarf.DW_ABRV_PARAM_LOCLIST
206 }
207 if n.Esc() == ir.EscHeap {
208
209
210
211 }
212 inlIndex := 0
213 if base.Flag.GenDwarfInl > 1 {
214 if n.InlFormal() || n.InlLocal() {
215 inlIndex = posInlIndex(n.Pos()) + 1
216 if n.InlFormal() {
217 abbrev = dwarf.DW_ABRV_PARAM_LOCLIST
218 }
219 }
220 }
221 declpos := base.Ctxt.InnermostPos(n.Pos())
222 vars = append(vars, &dwarf.Var{
223 Name: n.Sym().Name,
224 IsReturnValue: isReturnValue,
225 Abbrev: abbrev,
226 StackOffset: int32(n.FrameOffset()),
227 Type: base.Ctxt.Lookup(typename),
228 DeclFile: declpos.RelFilename(),
229 DeclLine: declpos.RelLine(),
230 DeclCol: declpos.RelCol(),
231 InlIndex: int32(inlIndex),
232 ChildIndex: -1,
233 DictIndex: n.DictIndex,
234 })
235
236 fnsym.Func().RecordAutoType(reflectdata.TypeLinksym(n.Type()))
237 }
238
239
240 sortDeclsAndVars(fn, decls, vars)
241
242 return decls, vars
243 }
244
245
246
247
248
249
250
251 func sortDeclsAndVars(fn *ir.Func, decls []*ir.Name, vars []*dwarf.Var) {
252 paramOrder := make(map[*ir.Name]int)
253 idx := 1
254 for _, selfn := range types.RecvsParamsResults {
255 fsl := selfn(fn.Type()).FieldSlice()
256 for _, f := range fsl {
257 if n, ok := f.Nname.(*ir.Name); ok {
258 paramOrder[n] = idx
259 idx++
260 }
261 }
262 }
263 sort.Stable(varsAndDecls{decls, vars, paramOrder})
264 }
265
266 type varsAndDecls struct {
267 decls []*ir.Name
268 vars []*dwarf.Var
269 paramOrder map[*ir.Name]int
270 }
271
272 func (v varsAndDecls) Len() int {
273 return len(v.decls)
274 }
275
276 func (v varsAndDecls) Less(i, j int) bool {
277 nameLT := func(ni, nj *ir.Name) bool {
278 oi, foundi := v.paramOrder[ni]
279 oj, foundj := v.paramOrder[nj]
280 if foundi {
281 if foundj {
282 return oi < oj
283 } else {
284 return true
285 }
286 }
287 return false
288 }
289 return nameLT(v.decls[i], v.decls[j])
290 }
291
292 func (v varsAndDecls) Swap(i, j int) {
293 v.vars[i], v.vars[j] = v.vars[j], v.vars[i]
294 v.decls[i], v.decls[j] = v.decls[j], v.decls[i]
295 }
296
297
298
299
300
301
302
303 func preInliningDcls(fnsym *obj.LSym) []*ir.Name {
304 fn := base.Ctxt.DwFixups.GetPrecursorFunc(fnsym).(*ir.Func)
305 var rdcl []*ir.Name
306 for _, n := range fn.Inl.Dcl {
307 c := n.Sym().Name[0]
308
309
310 if unversion(n.Sym().Name) == "_" || c == '.' || n.Type().IsUntyped() {
311 continue
312 }
313 rdcl = append(rdcl, n)
314 }
315 return rdcl
316 }
317
318
319
320 func createSimpleVars(fnsym *obj.LSym, apDecls []*ir.Name) ([]*ir.Name, []*dwarf.Var, ir.NameSet) {
321 var vars []*dwarf.Var
322 var decls []*ir.Name
323 var selected ir.NameSet
324 for _, n := range apDecls {
325 if ir.IsAutoTmp(n) {
326 continue
327 }
328
329 decls = append(decls, n)
330 vars = append(vars, createSimpleVar(fnsym, n))
331 selected.Add(n)
332 }
333 return decls, vars, selected
334 }
335
336 func createSimpleVar(fnsym *obj.LSym, n *ir.Name) *dwarf.Var {
337 var abbrev int
338 var offs int64
339
340 localAutoOffset := func() int64 {
341 offs = n.FrameOffset()
342 if base.Ctxt.FixedFrameSize() == 0 {
343 offs -= int64(types.PtrSize)
344 }
345 if buildcfg.FramePointerEnabled {
346 offs -= int64(types.PtrSize)
347 }
348 return offs
349 }
350
351 switch n.Class {
352 case ir.PAUTO:
353 offs = localAutoOffset()
354 abbrev = dwarf.DW_ABRV_AUTO
355 case ir.PPARAM, ir.PPARAMOUT:
356 abbrev = dwarf.DW_ABRV_PARAM
357 if n.IsOutputParamInRegisters() {
358 offs = localAutoOffset()
359 } else {
360 offs = n.FrameOffset() + base.Ctxt.FixedFrameSize()
361 }
362
363 default:
364 base.Fatalf("createSimpleVar unexpected class %v for node %v", n.Class, n)
365 }
366
367 typename := dwarf.InfoPrefix + types.TypeSymName(n.Type())
368 delete(fnsym.Func().Autot, reflectdata.TypeLinksym(n.Type()))
369 inlIndex := 0
370 if base.Flag.GenDwarfInl > 1 {
371 if n.InlFormal() || n.InlLocal() {
372 inlIndex = posInlIndex(n.Pos()) + 1
373 if n.InlFormal() {
374 abbrev = dwarf.DW_ABRV_PARAM
375 }
376 }
377 }
378 declpos := base.Ctxt.InnermostPos(declPos(n))
379 return &dwarf.Var{
380 Name: n.Sym().Name,
381 IsReturnValue: n.Class == ir.PPARAMOUT,
382 IsInlFormal: n.InlFormal(),
383 Abbrev: abbrev,
384 StackOffset: int32(offs),
385 Type: base.Ctxt.Lookup(typename),
386 DeclFile: declpos.RelFilename(),
387 DeclLine: declpos.RelLine(),
388 DeclCol: declpos.RelCol(),
389 InlIndex: int32(inlIndex),
390 ChildIndex: -1,
391 DictIndex: n.DictIndex,
392 }
393 }
394
395
396
397
398
399
400 func createABIVars(fnsym *obj.LSym, fn *ir.Func, apDecls []*ir.Name) ([]*ir.Name, []*dwarf.Var, ir.NameSet) {
401
402
403
404 decls, vars, selected := createComplexVars(fnsym, fn)
405
406
407
408
409 for _, n := range apDecls {
410 if ir.IsAutoTmp(n) {
411 continue
412 }
413 if _, ok := selected[n]; ok {
414
415 continue
416 }
417
418 decls = append(decls, n)
419 vars = append(vars, createSimpleVar(fnsym, n))
420 selected.Add(n)
421 }
422
423 return decls, vars, selected
424 }
425
426
427
428 func createComplexVars(fnsym *obj.LSym, fn *ir.Func) ([]*ir.Name, []*dwarf.Var, ir.NameSet) {
429 debugInfo := fn.DebugInfo.(*ssa.FuncDebug)
430
431
432 var decls []*ir.Name
433 var vars []*dwarf.Var
434 var ssaVars ir.NameSet
435
436 for varID, dvar := range debugInfo.Vars {
437 n := dvar
438 ssaVars.Add(n)
439 for _, slot := range debugInfo.VarSlots[varID] {
440 ssaVars.Add(debugInfo.Slots[slot].N)
441 }
442
443 if dvar := createComplexVar(fnsym, fn, ssa.VarID(varID)); dvar != nil {
444 decls = append(decls, n)
445 vars = append(vars, dvar)
446 }
447 }
448
449 return decls, vars, ssaVars
450 }
451
452
453 func createComplexVar(fnsym *obj.LSym, fn *ir.Func, varID ssa.VarID) *dwarf.Var {
454 debug := fn.DebugInfo.(*ssa.FuncDebug)
455 n := debug.Vars[varID]
456
457 var abbrev int
458 switch n.Class {
459 case ir.PAUTO:
460 abbrev = dwarf.DW_ABRV_AUTO_LOCLIST
461 case ir.PPARAM, ir.PPARAMOUT:
462 abbrev = dwarf.DW_ABRV_PARAM_LOCLIST
463 default:
464 return nil
465 }
466
467 gotype := reflectdata.TypeLinksym(n.Type())
468 delete(fnsym.Func().Autot, gotype)
469 typename := dwarf.InfoPrefix + gotype.Name[len("type."):]
470 inlIndex := 0
471 if base.Flag.GenDwarfInl > 1 {
472 if n.InlFormal() || n.InlLocal() {
473 inlIndex = posInlIndex(n.Pos()) + 1
474 if n.InlFormal() {
475 abbrev = dwarf.DW_ABRV_PARAM_LOCLIST
476 }
477 }
478 }
479 declpos := base.Ctxt.InnermostPos(n.Pos())
480 dvar := &dwarf.Var{
481 Name: n.Sym().Name,
482 IsReturnValue: n.Class == ir.PPARAMOUT,
483 IsInlFormal: n.InlFormal(),
484 Abbrev: abbrev,
485 Type: base.Ctxt.Lookup(typename),
486
487
488
489
490 StackOffset: ssagen.StackOffset(debug.Slots[debug.VarSlots[varID][0]]),
491 DeclFile: declpos.RelFilename(),
492 DeclLine: declpos.RelLine(),
493 DeclCol: declpos.RelCol(),
494 InlIndex: int32(inlIndex),
495 ChildIndex: -1,
496 DictIndex: n.DictIndex,
497 }
498 list := debug.LocationLists[varID]
499 if len(list) != 0 {
500 dvar.PutLocationList = func(listSym, startPC dwarf.Sym) {
501 debug.PutLocationList(list, base.Ctxt, listSym.(*obj.LSym), startPC.(*obj.LSym))
502 }
503 }
504 return dvar
505 }
506
507
508
509 func RecordFlags(flags ...string) {
510 if base.Ctxt.Pkgpath == "" {
511
512
513 return
514 }
515
516 type BoolFlag interface {
517 IsBoolFlag() bool
518 }
519 type CountFlag interface {
520 IsCountFlag() bool
521 }
522 var cmd bytes.Buffer
523 for _, name := range flags {
524 f := flag.Lookup(name)
525 if f == nil {
526 continue
527 }
528 getter := f.Value.(flag.Getter)
529 if getter.String() == f.DefValue {
530
531 continue
532 }
533 if bf, ok := f.Value.(BoolFlag); ok && bf.IsBoolFlag() {
534 val, ok := getter.Get().(bool)
535 if ok && val {
536 fmt.Fprintf(&cmd, " -%s", f.Name)
537 continue
538 }
539 }
540 if cf, ok := f.Value.(CountFlag); ok && cf.IsCountFlag() {
541 val, ok := getter.Get().(int)
542 if ok && val == 1 {
543 fmt.Fprintf(&cmd, " -%s", f.Name)
544 continue
545 }
546 }
547 fmt.Fprintf(&cmd, " -%s=%v", f.Name, getter.Get())
548 }
549
550
551
552
553
554 if buildcfg.Experiment.RegabiArgs {
555 cmd.Write([]byte(" regabi"))
556 }
557
558 if cmd.Len() == 0 {
559 return
560 }
561 s := base.Ctxt.Lookup(dwarf.CUInfoPrefix + "producer." + base.Ctxt.Pkgpath)
562 s.Type = objabi.SDWARFCUINFO
563
564
565 s.Set(obj.AttrDuplicateOK, true)
566 base.Ctxt.Data = append(base.Ctxt.Data, s)
567 s.P = cmd.Bytes()[1:]
568 }
569
570
571
572 func RecordPackageName() {
573 s := base.Ctxt.Lookup(dwarf.CUInfoPrefix + "packagename." + base.Ctxt.Pkgpath)
574 s.Type = objabi.SDWARFCUINFO
575
576
577 s.Set(obj.AttrDuplicateOK, true)
578 base.Ctxt.Data = append(base.Ctxt.Data, s)
579 s.P = []byte(types.LocalPkg.Name)
580 }
581
View as plain text