1
2
3
4
5
6
7
8
9
10
11
12
13
14 package ld
15
16 import (
17 "cmd/internal/dwarf"
18 "cmd/internal/obj"
19 "cmd/internal/objabi"
20 "cmd/internal/src"
21 "cmd/internal/sys"
22 "cmd/link/internal/loader"
23 "cmd/link/internal/sym"
24 "cmp"
25 "fmt"
26 "internal/abi"
27 "internal/buildcfg"
28 "log"
29 "path"
30 "runtime"
31 "slices"
32 "strings"
33 "sync"
34 )
35
36
37
38
39
40
41
42 type dwctxt struct {
43 linkctxt *Link
44 ldr *loader.Loader
45 arch *sys.Arch
46
47
48
49 tmap map[string]loader.Sym
50
51
52
53
54
55
56 rtmap map[loader.Sym]loader.Sym
57
58
59
60 tdmap map[loader.Sym]loader.Sym
61
62
63 typeRuntimeEface loader.Sym
64 typeRuntimeIface loader.Sym
65 uintptrInfoSym loader.Sym
66
67
68
69 dwmu *sync.Mutex
70 }
71
72
73
74
75 type dwSym loader.Sym
76
77 func (c dwctxt) PtrSize() int {
78 return c.arch.PtrSize
79 }
80
81 func (c dwctxt) Size(s dwarf.Sym) int64 {
82 return int64(len(c.ldr.Data(loader.Sym(s.(dwSym)))))
83 }
84
85 func (c dwctxt) AddInt(s dwarf.Sym, size int, i int64) {
86 ds := loader.Sym(s.(dwSym))
87 dsu := c.ldr.MakeSymbolUpdater(ds)
88 dsu.AddUintXX(c.arch, uint64(i), size)
89 }
90
91 func (c dwctxt) AddBytes(s dwarf.Sym, b []byte) {
92 ds := loader.Sym(s.(dwSym))
93 dsu := c.ldr.MakeSymbolUpdater(ds)
94 dsu.AddBytes(b)
95 }
96
97 func (c dwctxt) AddString(s dwarf.Sym, v string) {
98 ds := loader.Sym(s.(dwSym))
99 dsu := c.ldr.MakeSymbolUpdater(ds)
100 dsu.Addstring(v)
101 }
102
103 func (c dwctxt) AddAddress(s dwarf.Sym, data interface{}, value int64) {
104 ds := loader.Sym(s.(dwSym))
105 dsu := c.ldr.MakeSymbolUpdater(ds)
106 if value != 0 {
107 value -= dsu.Value()
108 }
109 tgtds := loader.Sym(data.(dwSym))
110 dsu.AddAddrPlus(c.arch, tgtds, value)
111 }
112
113 func (c dwctxt) AddCURelativeAddress(s dwarf.Sym, data interface{}, value int64) {
114 ds := loader.Sym(s.(dwSym))
115 dsu := c.ldr.MakeSymbolUpdater(ds)
116 if value != 0 {
117 value -= dsu.Value()
118 }
119 tgtds := loader.Sym(data.(dwSym))
120 dsu.AddCURelativeAddrPlus(c.arch, tgtds, value)
121 }
122
123 func (c dwctxt) AddSectionOffset(s dwarf.Sym, size int, t interface{}, ofs int64) {
124 ds := loader.Sym(s.(dwSym))
125 dsu := c.ldr.MakeSymbolUpdater(ds)
126 tds := loader.Sym(t.(dwSym))
127 switch size {
128 default:
129 c.linkctxt.Errorf(ds, "invalid size %d in adddwarfref\n", size)
130 case c.arch.PtrSize, 4:
131 }
132 dsu.AddSymRef(c.arch, tds, ofs, objabi.R_ADDROFF, size)
133 }
134
135 func (c dwctxt) AddDWARFAddrSectionOffset(s dwarf.Sym, t interface{}, ofs int64) {
136 size := 4
137 if isDwarf64(c.linkctxt) {
138 size = 8
139 }
140 ds := loader.Sym(s.(dwSym))
141 dsu := c.ldr.MakeSymbolUpdater(ds)
142 tds := loader.Sym(t.(dwSym))
143 switch size {
144 default:
145 c.linkctxt.Errorf(ds, "invalid size %d in adddwarfref\n", size)
146 case c.arch.PtrSize, 4:
147 }
148 dsu.AddSymRef(c.arch, tds, ofs, objabi.R_DWARFSECREF, size)
149 }
150
151 func (c dwctxt) Logf(format string, args ...interface{}) {
152 c.linkctxt.Logf(format, args...)
153 }
154
155
156
157 func (c dwctxt) CurrentOffset(s dwarf.Sym) int64 {
158 panic("should be used only in the compiler")
159 }
160
161 func (c dwctxt) RecordDclReference(s dwarf.Sym, t dwarf.Sym, dclIdx int, inlIndex int) {
162 panic("should be used only in the compiler")
163 }
164
165 func (c dwctxt) RecordChildDieOffsets(s dwarf.Sym, vars []*dwarf.Var, offsets []int32) {
166 panic("should be used only in the compiler")
167 }
168
169 func isDwarf64(ctxt *Link) bool {
170 return ctxt.HeadType == objabi.Haix
171 }
172
173
174
175
176 const (
177 GdbScriptPythonFileId = 1
178 GdbScriptSchemeFileId = 3
179 GdbScriptPythonTextId = 4
180 GdbScriptSchemeTextId = 6
181 )
182
183 var gdbscript string
184
185
186
187
188
189
190
191
192
193
194
195 type dwarfSecInfo struct {
196 syms []loader.Sym
197 }
198
199
200 func (dsi *dwarfSecInfo) secSym() loader.Sym {
201 if len(dsi.syms) == 0 {
202 return 0
203 }
204 return dsi.syms[0]
205 }
206
207
208 func (dsi *dwarfSecInfo) subSyms() []loader.Sym {
209 if len(dsi.syms) == 0 {
210 return []loader.Sym{}
211 }
212 return dsi.syms[1:]
213 }
214
215
216
217 var dwarfp []dwarfSecInfo
218
219 func (d *dwctxt) writeabbrev() dwarfSecInfo {
220 abrvs := d.ldr.CreateSymForUpdate(".debug_abbrev", 0)
221 abrvs.SetType(sym.SDWARFSECT)
222 abrvs.AddBytes(dwarf.GetAbbrev())
223 return dwarfSecInfo{syms: []loader.Sym{abrvs.Sym()}}
224 }
225
226 var dwtypes dwarf.DWDie
227
228
229
230
231
232
233
234
235 func newattr(die *dwarf.DWDie, attr uint16, cls int, value int64, data interface{}) {
236 a := new(dwarf.DWAttr)
237 a.Link = die.Attr
238 die.Attr = a
239 a.Atr = attr
240 a.Cls = uint8(cls)
241 a.Value = value
242 a.Data = data
243 }
244
245
246
247
248 func getattr(die *dwarf.DWDie, attr uint16) *dwarf.DWAttr {
249 if die.Attr.Atr == attr {
250 return die.Attr
251 }
252
253 a := die.Attr
254 b := a.Link
255 for b != nil {
256 if b.Atr == attr {
257 a.Link = b.Link
258 b.Link = die.Attr
259 die.Attr = b
260 return b
261 }
262
263 a = b
264 b = b.Link
265 }
266
267 return nil
268 }
269
270
271
272
273
274
275 func (d *dwctxt) newdie(parent *dwarf.DWDie, abbrev int, name string) *dwarf.DWDie {
276 die := new(dwarf.DWDie)
277 die.Abbrev = abbrev
278 die.Link = parent.Child
279 parent.Child = die
280
281 newattr(die, dwarf.DW_AT_name, dwarf.DW_CLS_STRING, int64(len(name)), name)
282
283
284 if name == "" {
285 panic("nameless DWARF DIE")
286 }
287
288 var st sym.SymKind
289 switch abbrev {
290 case dwarf.DW_ABRV_FUNCTYPEPARAM, dwarf.DW_ABRV_FUNCTYPEOUTPARAM, dwarf.DW_ABRV_DOTDOTDOT, dwarf.DW_ABRV_STRUCTFIELD, dwarf.DW_ABRV_ARRAYRANGE:
291
292
293 return die
294 case dwarf.DW_ABRV_COMPUNIT, dwarf.DW_ABRV_COMPUNIT_TEXTLESS:
295
296 name = fmt.Sprintf(".pkg.%s.%d", name, len(d.linkctxt.compUnits))
297 st = sym.SDWARFCUINFO
298 case dwarf.DW_ABRV_VARIABLE:
299 st = sym.SDWARFVAR
300 default:
301
302
303 st = sym.SDWARFTYPE
304 }
305 ds := d.ldr.LookupOrCreateSym(dwarf.InfoPrefix+name, 0)
306 dsu := d.ldr.MakeSymbolUpdater(ds)
307 dsu.SetType(st)
308 d.ldr.SetAttrNotInSymbolTable(ds, true)
309 d.ldr.SetAttrReachable(ds, true)
310 die.Sym = dwSym(ds)
311 if abbrev >= dwarf.DW_ABRV_NULLTYPE && abbrev <= dwarf.DW_ABRV_TYPEDECL {
312 d.tmap[name] = ds
313 }
314
315 return die
316 }
317
318 func walktypedef(die *dwarf.DWDie) *dwarf.DWDie {
319 if die == nil {
320 return nil
321 }
322
323 if die.Abbrev == dwarf.DW_ABRV_TYPEDECL {
324 for attr := die.Attr; attr != nil; attr = attr.Link {
325 if attr.Atr == dwarf.DW_AT_type && attr.Cls == dwarf.DW_CLS_REFERENCE && attr.Data != nil {
326 return attr.Data.(*dwarf.DWDie)
327 }
328 }
329 }
330
331 return die
332 }
333
334 func (d *dwctxt) walksymtypedef(symIdx loader.Sym) loader.Sym {
335
336
337
338
339
340
341 if ts, ok := d.rtmap[symIdx]; ok {
342 if def, ok := d.tdmap[ts]; ok {
343 return def
344 }
345 d.linkctxt.Errorf(ts, "internal error: no entry for sym %d in tdmap\n", ts)
346 return 0
347 }
348 d.linkctxt.Errorf(symIdx, "internal error: no entry for sym %d in rtmap\n", symIdx)
349 return 0
350 }
351
352
353
354 func findchild(die *dwarf.DWDie, name string) *dwarf.DWDie {
355 var prev *dwarf.DWDie
356 for ; die != prev; prev, die = die, walktypedef(die) {
357 for a := die.Child; a != nil; a = a.Link {
358 if name == getattr(a, dwarf.DW_AT_name).Data {
359 return a
360 }
361 }
362 continue
363 }
364 return nil
365 }
366
367
368
369 func (d *dwctxt) find(name string) loader.Sym {
370 return d.tmap[name]
371 }
372
373 func (d *dwctxt) mustFind(name string) loader.Sym {
374 r := d.find(name)
375 if r == 0 {
376 Exitf("dwarf find: cannot find %s", name)
377 }
378 return r
379 }
380
381 func (d *dwctxt) adddwarfref(sb *loader.SymbolBuilder, t loader.Sym, size int) {
382 switch size {
383 default:
384 d.linkctxt.Errorf(sb.Sym(), "invalid size %d in adddwarfref\n", size)
385 case d.arch.PtrSize, 4:
386 }
387 sb.AddSymRef(d.arch, t, 0, objabi.R_DWARFSECREF, size)
388 }
389
390 func (d *dwctxt) newrefattr(die *dwarf.DWDie, attr uint16, ref loader.Sym) {
391 if ref == 0 {
392 return
393 }
394 newattr(die, attr, dwarf.DW_CLS_REFERENCE, 0, dwSym(ref))
395 }
396
397 func (d *dwctxt) dtolsym(s dwarf.Sym) loader.Sym {
398 if s == nil {
399 return 0
400 }
401 dws := loader.Sym(s.(dwSym))
402 return dws
403 }
404
405 func (d *dwctxt) putdie(syms []loader.Sym, die *dwarf.DWDie) []loader.Sym {
406 s := d.dtolsym(die.Sym)
407 if s == 0 {
408 s = syms[len(syms)-1]
409 } else {
410 syms = append(syms, s)
411 }
412 sDwsym := dwSym(s)
413 dwarf.Uleb128put(d, sDwsym, int64(die.Abbrev))
414 dwarf.PutAttrs(d, sDwsym, die.Abbrev, die.Attr)
415 if dwarf.HasChildren(die) {
416 for die := die.Child; die != nil; die = die.Link {
417 syms = d.putdie(syms, die)
418 }
419 dsu := d.ldr.MakeSymbolUpdater(syms[len(syms)-1])
420 dsu.AddUint8(0)
421 }
422 return syms
423 }
424
425 func reverselist(list **dwarf.DWDie) {
426 curr := *list
427 var prev *dwarf.DWDie
428 for curr != nil {
429 next := curr.Link
430 curr.Link = prev
431 prev = curr
432 curr = next
433 }
434
435 *list = prev
436 }
437
438 func reversetree(list **dwarf.DWDie) {
439 reverselist(list)
440 for die := *list; die != nil; die = die.Link {
441 if dwarf.HasChildren(die) {
442 reversetree(&die.Child)
443 }
444 }
445 }
446
447 func newmemberoffsetattr(die *dwarf.DWDie, offs int32) {
448 newattr(die, dwarf.DW_AT_data_member_location, dwarf.DW_CLS_CONSTANT, int64(offs), nil)
449 }
450
451 func (d *dwctxt) lookupOrDiag(n string) loader.Sym {
452 symIdx := d.ldr.Lookup(n, 0)
453 if symIdx == 0 {
454 Exitf("dwarf: missing type: %s", n)
455 }
456 if len(d.ldr.Data(symIdx)) == 0 {
457 Exitf("dwarf: missing type (no data): %s", n)
458 }
459
460 return symIdx
461 }
462
463 func (d *dwctxt) dotypedef(parent *dwarf.DWDie, name string, def *dwarf.DWDie) *dwarf.DWDie {
464
465 if strings.HasPrefix(name, "map[") {
466 return nil
467 }
468 if strings.HasPrefix(name, "struct {") {
469 return nil
470 }
471
472
473 if strings.HasPrefix(name, "noalg.struct {") {
474 return nil
475 }
476 if strings.HasPrefix(name, "chan ") {
477 return nil
478 }
479 if name[0] == '[' || name[0] == '*' {
480 return nil
481 }
482 if def == nil {
483 Errorf("dwarf: bad def in dotypedef")
484 }
485
486
487
488
489 tds := d.ldr.CreateExtSym("", 0)
490 tdsu := d.ldr.MakeSymbolUpdater(tds)
491 tdsu.SetType(sym.SDWARFTYPE)
492 def.Sym = dwSym(tds)
493 d.ldr.SetAttrNotInSymbolTable(tds, true)
494 d.ldr.SetAttrReachable(tds, true)
495
496
497
498
499
500 die := d.newdie(parent, dwarf.DW_ABRV_TYPEDECL, name)
501
502 d.newrefattr(die, dwarf.DW_AT_type, tds)
503
504 return die
505 }
506
507
508 func (d *dwctxt) defgotype(gotype loader.Sym) loader.Sym {
509 if gotype == 0 {
510 return d.mustFind("<unspecified>")
511 }
512
513
514 if ds, ok := d.tdmap[gotype]; ok {
515 return ds
516 }
517
518 sn := d.ldr.SymName(gotype)
519 if !strings.HasPrefix(sn, "type:") {
520 d.linkctxt.Errorf(gotype, "dwarf: type name doesn't start with \"type:\"")
521 return d.mustFind("<unspecified>")
522 }
523 name := sn[5:]
524
525 sdie := d.find(name)
526 if sdie != 0 {
527 return sdie
528 }
529
530 gtdwSym := d.newtype(gotype)
531 d.tdmap[gotype] = loader.Sym(gtdwSym.Sym.(dwSym))
532 return loader.Sym(gtdwSym.Sym.(dwSym))
533 }
534
535 func (d *dwctxt) newtype(gotype loader.Sym) *dwarf.DWDie {
536 sn := d.ldr.SymName(gotype)
537 name := sn[5:]
538 tdata := d.ldr.Data(gotype)
539 if len(tdata) == 0 {
540 d.linkctxt.Errorf(gotype, "missing type")
541 }
542 kind := decodetypeKind(d.arch, tdata)
543 bytesize := decodetypeSize(d.arch, tdata)
544
545 var die, typedefdie *dwarf.DWDie
546 switch kind {
547 case abi.Bool:
548 die = d.newdie(&dwtypes, dwarf.DW_ABRV_BASETYPE, name)
549 newattr(die, dwarf.DW_AT_encoding, dwarf.DW_CLS_CONSTANT, dwarf.DW_ATE_boolean, 0)
550 newattr(die, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, bytesize, 0)
551
552 case abi.Int,
553 abi.Int8,
554 abi.Int16,
555 abi.Int32,
556 abi.Int64:
557 die = d.newdie(&dwtypes, dwarf.DW_ABRV_BASETYPE, name)
558 newattr(die, dwarf.DW_AT_encoding, dwarf.DW_CLS_CONSTANT, dwarf.DW_ATE_signed, 0)
559 newattr(die, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, bytesize, 0)
560
561 case abi.Uint,
562 abi.Uint8,
563 abi.Uint16,
564 abi.Uint32,
565 abi.Uint64,
566 abi.Uintptr:
567 die = d.newdie(&dwtypes, dwarf.DW_ABRV_BASETYPE, name)
568 newattr(die, dwarf.DW_AT_encoding, dwarf.DW_CLS_CONSTANT, dwarf.DW_ATE_unsigned, 0)
569 newattr(die, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, bytesize, 0)
570
571 case abi.Float32,
572 abi.Float64:
573 die = d.newdie(&dwtypes, dwarf.DW_ABRV_BASETYPE, name)
574 newattr(die, dwarf.DW_AT_encoding, dwarf.DW_CLS_CONSTANT, dwarf.DW_ATE_float, 0)
575 newattr(die, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, bytesize, 0)
576
577 case abi.Complex64,
578 abi.Complex128:
579 die = d.newdie(&dwtypes, dwarf.DW_ABRV_BASETYPE, name)
580 newattr(die, dwarf.DW_AT_encoding, dwarf.DW_CLS_CONSTANT, dwarf.DW_ATE_complex_float, 0)
581 newattr(die, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, bytesize, 0)
582
583 case abi.Array:
584 die = d.newdie(&dwtypes, dwarf.DW_ABRV_ARRAYTYPE, name)
585 typedefdie = d.dotypedef(&dwtypes, name, die)
586 newattr(die, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, bytesize, 0)
587 s := decodetypeArrayElem(d.ldr, d.arch, gotype)
588 d.newrefattr(die, dwarf.DW_AT_type, d.defgotype(s))
589 fld := d.newdie(die, dwarf.DW_ABRV_ARRAYRANGE, "range")
590
591
592 newattr(fld, dwarf.DW_AT_count, dwarf.DW_CLS_CONSTANT, decodetypeArrayLen(d.ldr, d.arch, gotype), 0)
593
594 d.newrefattr(fld, dwarf.DW_AT_type, d.uintptrInfoSym)
595
596 case abi.Chan:
597 die = d.newdie(&dwtypes, dwarf.DW_ABRV_CHANTYPE, name)
598 s := decodetypeChanElem(d.ldr, d.arch, gotype)
599 d.newrefattr(die, dwarf.DW_AT_go_elem, d.defgotype(s))
600
601
602 d.newrefattr(die, dwarf.DW_AT_type, s)
603
604 case abi.Func:
605 die = d.newdie(&dwtypes, dwarf.DW_ABRV_FUNCTYPE, name)
606 newattr(die, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, bytesize, 0)
607 typedefdie = d.dotypedef(&dwtypes, name, die)
608 data := d.ldr.Data(gotype)
609
610 relocs := d.ldr.Relocs(gotype)
611 nfields := decodetypeFuncInCount(d.arch, data)
612 for i := 0; i < nfields; i++ {
613 s := decodetypeFuncInType(d.ldr, d.arch, gotype, &relocs, i)
614 sn := d.ldr.SymName(s)
615 fld := d.newdie(die, dwarf.DW_ABRV_FUNCTYPEPARAM, sn[5:])
616 d.newrefattr(fld, dwarf.DW_AT_type, d.defgotype(s))
617 }
618
619 if decodetypeFuncDotdotdot(d.arch, data) {
620 d.newdie(die, dwarf.DW_ABRV_DOTDOTDOT, "...")
621 }
622 nfields = decodetypeFuncOutCount(d.arch, data)
623 for i := 0; i < nfields; i++ {
624 s := decodetypeFuncOutType(d.ldr, d.arch, gotype, &relocs, i)
625 sn := d.ldr.SymName(s)
626 fld := d.newdie(die, dwarf.DW_ABRV_FUNCTYPEOUTPARAM, sn[5:])
627 newattr(fld, dwarf.DW_AT_variable_parameter, dwarf.DW_CLS_FLAG, 1, 0)
628 d.newrefattr(fld, dwarf.DW_AT_type, d.defgotype(s))
629 }
630
631 case abi.Interface:
632 die = d.newdie(&dwtypes, dwarf.DW_ABRV_IFACETYPE, name)
633 typedefdie = d.dotypedef(&dwtypes, name, die)
634 data := d.ldr.Data(gotype)
635 nfields := int(decodetypeIfaceMethodCount(d.arch, data))
636 var s loader.Sym
637 if nfields == 0 {
638 s = d.typeRuntimeEface
639 } else {
640 s = d.typeRuntimeIface
641 }
642 d.newrefattr(die, dwarf.DW_AT_type, d.defgotype(s))
643
644 case abi.Map:
645 die = d.newdie(&dwtypes, dwarf.DW_ABRV_MAPTYPE, name)
646 s := decodetypeMapKey(d.ldr, d.arch, gotype)
647 d.newrefattr(die, dwarf.DW_AT_go_key, d.defgotype(s))
648 s = decodetypeMapValue(d.ldr, d.arch, gotype)
649 d.newrefattr(die, dwarf.DW_AT_go_elem, d.defgotype(s))
650
651
652 d.newrefattr(die, dwarf.DW_AT_type, gotype)
653
654 case abi.Pointer:
655 die = d.newdie(&dwtypes, dwarf.DW_ABRV_PTRTYPE, name)
656 typedefdie = d.dotypedef(&dwtypes, name, die)
657 s := decodetypePtrElem(d.ldr, d.arch, gotype)
658 d.newrefattr(die, dwarf.DW_AT_type, d.defgotype(s))
659
660 case abi.Slice:
661 die = d.newdie(&dwtypes, dwarf.DW_ABRV_SLICETYPE, name)
662 typedefdie = d.dotypedef(&dwtypes, name, die)
663 newattr(die, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, bytesize, 0)
664 s := decodetypeArrayElem(d.ldr, d.arch, gotype)
665 elem := d.defgotype(s)
666 d.newrefattr(die, dwarf.DW_AT_go_elem, elem)
667
668 case abi.String:
669 die = d.newdie(&dwtypes, dwarf.DW_ABRV_STRINGTYPE, name)
670 newattr(die, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, bytesize, 0)
671
672 case abi.Struct:
673 die = d.newdie(&dwtypes, dwarf.DW_ABRV_STRUCTTYPE, name)
674 typedefdie = d.dotypedef(&dwtypes, name, die)
675 newattr(die, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, bytesize, 0)
676 nfields := decodetypeStructFieldCount(d.ldr, d.arch, gotype)
677 for i := 0; i < nfields; i++ {
678 f := decodetypeStructFieldName(d.ldr, d.arch, gotype, i)
679 s := decodetypeStructFieldType(d.ldr, d.arch, gotype, i)
680 if f == "" {
681 sn := d.ldr.SymName(s)
682 f = sn[5:]
683 }
684 fld := d.newdie(die, dwarf.DW_ABRV_STRUCTFIELD, f)
685 d.newrefattr(fld, dwarf.DW_AT_type, d.defgotype(s))
686 offset := decodetypeStructFieldOffset(d.ldr, d.arch, gotype, i)
687 newmemberoffsetattr(fld, int32(offset))
688 if decodetypeStructFieldEmbedded(d.ldr, d.arch, gotype, i) {
689 newattr(fld, dwarf.DW_AT_go_embedded_field, dwarf.DW_CLS_FLAG, 1, 0)
690 }
691 }
692
693 case abi.UnsafePointer:
694 die = d.newdie(&dwtypes, dwarf.DW_ABRV_BARE_PTRTYPE, name)
695
696 default:
697 d.linkctxt.Errorf(gotype, "dwarf: definition of unknown kind %d", kind)
698 die = d.newdie(&dwtypes, dwarf.DW_ABRV_TYPEDECL, name)
699 d.newrefattr(die, dwarf.DW_AT_type, d.mustFind("<unspecified>"))
700 }
701
702 newattr(die, dwarf.DW_AT_go_kind, dwarf.DW_CLS_CONSTANT, int64(kind), 0)
703
704 if d.ldr.AttrReachable(gotype) {
705 newattr(die, dwarf.DW_AT_go_runtime_type, dwarf.DW_CLS_GO_TYPEREF, 0, dwSym(gotype))
706 }
707
708
709 if _, ok := d.rtmap[gotype]; ok {
710 log.Fatalf("internal error: rtmap entry already installed\n")
711 }
712
713 ds := loader.Sym(die.Sym.(dwSym))
714 if typedefdie != nil {
715 ds = loader.Sym(typedefdie.Sym.(dwSym))
716 }
717 d.rtmap[ds] = gotype
718
719 if _, ok := prototypedies[sn]; ok {
720 prototypedies[sn] = die
721 }
722
723 if typedefdie != nil {
724 return typedefdie
725 }
726 return die
727 }
728
729 func (d *dwctxt) nameFromDIESym(dwtypeDIESym loader.Sym) string {
730 sn := d.ldr.SymName(dwtypeDIESym)
731 return sn[len(dwarf.InfoPrefix):]
732 }
733
734 func (d *dwctxt) defptrto(dwtype loader.Sym) loader.Sym {
735
736
737
738
739
740 ptrname := "*" + d.nameFromDIESym(dwtype)
741 if die := d.find(ptrname); die != 0 {
742 return die
743 }
744
745 pdie := d.newdie(&dwtypes, dwarf.DW_ABRV_PTRTYPE, ptrname)
746 d.newrefattr(pdie, dwarf.DW_AT_type, dwtype)
747
748
749
750
751 gts := d.ldr.Lookup("type:"+ptrname, 0)
752 if gts != 0 && d.ldr.AttrReachable(gts) {
753 newattr(pdie, dwarf.DW_AT_go_kind, dwarf.DW_CLS_CONSTANT, int64(abi.Pointer), 0)
754 newattr(pdie, dwarf.DW_AT_go_runtime_type, dwarf.DW_CLS_GO_TYPEREF, 0, dwSym(gts))
755 }
756
757 if gts != 0 {
758 ds := loader.Sym(pdie.Sym.(dwSym))
759 d.rtmap[ds] = gts
760 d.tdmap[gts] = ds
761 }
762
763 return d.dtolsym(pdie.Sym)
764 }
765
766
767
768
769 func (d *dwctxt) copychildrenexcept(ctxt *Link, dst *dwarf.DWDie, src *dwarf.DWDie, except *dwarf.DWDie) {
770 for src = src.Child; src != nil; src = src.Link {
771 if src == except {
772 continue
773 }
774 c := d.newdie(dst, src.Abbrev, getattr(src, dwarf.DW_AT_name).Data.(string))
775 for a := src.Attr; a != nil; a = a.Link {
776 newattr(c, a.Atr, int(a.Cls), a.Value, a.Data)
777 }
778 d.copychildrenexcept(ctxt, c, src, nil)
779 }
780
781 reverselist(&dst.Child)
782 }
783
784 func (d *dwctxt) copychildren(ctxt *Link, dst *dwarf.DWDie, src *dwarf.DWDie) {
785 d.copychildrenexcept(ctxt, dst, src, nil)
786 }
787
788
789
790 func (d *dwctxt) substitutetype(structdie *dwarf.DWDie, field string, dwtype loader.Sym) {
791 child := findchild(structdie, field)
792 if child == nil {
793 Exitf("dwarf substitutetype: %s does not have member %s",
794 getattr(structdie, dwarf.DW_AT_name).Data, field)
795 return
796 }
797
798 a := getattr(child, dwarf.DW_AT_type)
799 if a != nil {
800 a.Data = dwSym(dwtype)
801 } else {
802 d.newrefattr(child, dwarf.DW_AT_type, dwtype)
803 }
804 }
805
806 func (d *dwctxt) findprotodie(ctxt *Link, name string) *dwarf.DWDie {
807 die, ok := prototypedies[name]
808 if ok && die == nil {
809 d.defgotype(d.lookupOrDiag(name))
810 die = prototypedies[name]
811 }
812 if die == nil {
813 log.Fatalf("internal error: DIE generation failed for %s\n", name)
814 }
815 return die
816 }
817
818 func (d *dwctxt) synthesizestringtypes(ctxt *Link, die *dwarf.DWDie) {
819 prototype := walktypedef(d.findprotodie(ctxt, "type:runtime.stringStructDWARF"))
820 if prototype == nil {
821 return
822 }
823
824 for ; die != nil; die = die.Link {
825 if die.Abbrev != dwarf.DW_ABRV_STRINGTYPE {
826 continue
827 }
828 d.copychildren(ctxt, die, prototype)
829 }
830 }
831
832 func (d *dwctxt) synthesizeslicetypes(ctxt *Link, die *dwarf.DWDie) {
833 prototype := walktypedef(d.findprotodie(ctxt, "type:runtime.slice"))
834 if prototype == nil {
835 return
836 }
837
838 for ; die != nil; die = die.Link {
839 if die.Abbrev != dwarf.DW_ABRV_SLICETYPE {
840 continue
841 }
842 d.copychildren(ctxt, die, prototype)
843 elem := loader.Sym(getattr(die, dwarf.DW_AT_go_elem).Data.(dwSym))
844 d.substitutetype(die, "array", d.defptrto(elem))
845 }
846 }
847
848 func mkinternaltypename(base string, arg1 string, arg2 string) string {
849 if arg2 == "" {
850 return fmt.Sprintf("%s<%s>", base, arg1)
851 }
852 return fmt.Sprintf("%s<%s,%s>", base, arg1, arg2)
853 }
854
855 func (d *dwctxt) mkinternaltype(ctxt *Link, abbrev int, typename, keyname, valname string, f func(*dwarf.DWDie)) loader.Sym {
856 name := mkinternaltypename(typename, keyname, valname)
857 symname := dwarf.InfoPrefix + name
858 s := d.ldr.Lookup(symname, 0)
859 if s != 0 && d.ldr.SymType(s) == sym.SDWARFTYPE {
860 return s
861 }
862 die := d.newdie(&dwtypes, abbrev, name)
863 f(die)
864 return d.dtolsym(die.Sym)
865 }
866
867 func (d *dwctxt) synthesizemaptypes(ctxt *Link, die *dwarf.DWDie) {
868 if buildcfg.Experiment.SwissMap {
869 d.synthesizemaptypesSwiss(ctxt, die)
870 } else {
871 d.synthesizemaptypesOld(ctxt, die)
872 }
873 }
874
875 func (d *dwctxt) synthesizemaptypesSwiss(ctxt *Link, die *dwarf.DWDie) {
876 mapType := walktypedef(d.findprotodie(ctxt, "type:internal/runtime/maps.Map"))
877 tableType := walktypedef(d.findprotodie(ctxt, "type:internal/runtime/maps.table"))
878 groupsReferenceType := walktypedef(d.findprotodie(ctxt, "type:internal/runtime/maps.groupsReference"))
879
880 for ; die != nil; die = die.Link {
881 if die.Abbrev != dwarf.DW_ABRV_MAPTYPE {
882 continue
883 }
884 gotype := loader.Sym(getattr(die, dwarf.DW_AT_type).Data.(dwSym))
885
886 keyType := decodetypeMapKey(d.ldr, d.arch, gotype)
887 valType := decodetypeMapValue(d.ldr, d.arch, gotype)
888 groupType := decodetypeMapSwissGroup(d.ldr, d.arch, gotype)
889
890 keyType = d.walksymtypedef(d.defgotype(keyType))
891 valType = d.walksymtypedef(d.defgotype(valType))
892 groupType = d.walksymtypedef(d.defgotype(groupType))
893
894 keyName := d.nameFromDIESym(keyType)
895 valName := d.nameFromDIESym(valType)
896
897
898 dwGroupsReference := d.mkinternaltype(ctxt, dwarf.DW_ABRV_STRUCTTYPE, "groupReference", keyName, valName, func(dwh *dwarf.DWDie) {
899 d.copychildren(ctxt, dwh, groupsReferenceType)
900
901
902
903
904
905 d.substitutetype(dwh, "data", d.defptrto(groupType))
906 newattr(dwh, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, getattr(groupsReferenceType, dwarf.DW_AT_byte_size).Value, nil)
907 newattr(dwh, dwarf.DW_AT_go_kind, dwarf.DW_CLS_CONSTANT, int64(abi.Struct), 0)
908 })
909
910
911 dwTable := d.mkinternaltype(ctxt, dwarf.DW_ABRV_STRUCTTYPE, "table", keyName, valName, func(dwh *dwarf.DWDie) {
912 d.copychildren(ctxt, dwh, tableType)
913 d.substitutetype(dwh, "groups", dwGroupsReference)
914 newattr(dwh, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, getattr(tableType, dwarf.DW_AT_byte_size).Value, nil)
915 newattr(dwh, dwarf.DW_AT_go_kind, dwarf.DW_CLS_CONSTANT, int64(abi.Struct), 0)
916 })
917
918
919 dwMap := d.mkinternaltype(ctxt, dwarf.DW_ABRV_STRUCTTYPE, "map", keyName, valName, func(dwh *dwarf.DWDie) {
920 d.copychildren(ctxt, dwh, mapType)
921
922
923
924
925
926
927 d.substitutetype(dwh, "dirPtr", d.defptrto(d.defptrto(dwTable)))
928 newattr(dwh, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, getattr(mapType, dwarf.DW_AT_byte_size).Value, nil)
929 newattr(dwh, dwarf.DW_AT_go_kind, dwarf.DW_CLS_CONSTANT, int64(abi.Struct), 0)
930 })
931
932
933 d.newrefattr(die, dwarf.DW_AT_type, d.defptrto(dwMap))
934 }
935 }
936
937 func (d *dwctxt) synthesizemaptypesOld(ctxt *Link, die *dwarf.DWDie) {
938 hash := walktypedef(d.findprotodie(ctxt, "type:runtime.hmap"))
939 bucket := walktypedef(d.findprotodie(ctxt, "type:runtime.bmap"))
940
941 if hash == nil {
942 return
943 }
944
945 for ; die != nil; die = die.Link {
946 if die.Abbrev != dwarf.DW_ABRV_MAPTYPE {
947 continue
948 }
949 gotype := loader.Sym(getattr(die, dwarf.DW_AT_type).Data.(dwSym))
950 keytype := decodetypeMapKey(d.ldr, d.arch, gotype)
951 valtype := decodetypeMapValue(d.ldr, d.arch, gotype)
952 keydata := d.ldr.Data(keytype)
953 valdata := d.ldr.Data(valtype)
954 keysize, valsize := decodetypeSize(d.arch, keydata), decodetypeSize(d.arch, valdata)
955 keytype, valtype = d.walksymtypedef(d.defgotype(keytype)), d.walksymtypedef(d.defgotype(valtype))
956
957
958 indirectKey, indirectVal := false, false
959 if keysize > abi.OldMapMaxKeyBytes {
960 keysize = int64(d.arch.PtrSize)
961 indirectKey = true
962 }
963 if valsize > abi.OldMapMaxElemBytes {
964 valsize = int64(d.arch.PtrSize)
965 indirectVal = true
966 }
967
968
969 keyname := d.nameFromDIESym(keytype)
970 dwhks := d.mkinternaltype(ctxt, dwarf.DW_ABRV_ARRAYTYPE, "[]key", keyname, "", func(dwhk *dwarf.DWDie) {
971 newattr(dwhk, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, abi.OldMapBucketCount*keysize, 0)
972 t := keytype
973 if indirectKey {
974 t = d.defptrto(keytype)
975 }
976 d.newrefattr(dwhk, dwarf.DW_AT_type, t)
977 fld := d.newdie(dwhk, dwarf.DW_ABRV_ARRAYRANGE, "size")
978 newattr(fld, dwarf.DW_AT_count, dwarf.DW_CLS_CONSTANT, abi.OldMapBucketCount, 0)
979 d.newrefattr(fld, dwarf.DW_AT_type, d.uintptrInfoSym)
980 })
981
982
983 valname := d.nameFromDIESym(valtype)
984 dwhvs := d.mkinternaltype(ctxt, dwarf.DW_ABRV_ARRAYTYPE, "[]val", valname, "", func(dwhv *dwarf.DWDie) {
985 newattr(dwhv, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, abi.OldMapBucketCount*valsize, 0)
986 t := valtype
987 if indirectVal {
988 t = d.defptrto(valtype)
989 }
990 d.newrefattr(dwhv, dwarf.DW_AT_type, t)
991 fld := d.newdie(dwhv, dwarf.DW_ABRV_ARRAYRANGE, "size")
992 newattr(fld, dwarf.DW_AT_count, dwarf.DW_CLS_CONSTANT, abi.OldMapBucketCount, 0)
993 d.newrefattr(fld, dwarf.DW_AT_type, d.uintptrInfoSym)
994 })
995
996
997 dwhbs := d.mkinternaltype(ctxt, dwarf.DW_ABRV_STRUCTTYPE, "bucket", keyname, valname, func(dwhb *dwarf.DWDie) {
998
999
1000 d.copychildrenexcept(ctxt, dwhb, bucket, findchild(bucket, "data"))
1001
1002 fld := d.newdie(dwhb, dwarf.DW_ABRV_STRUCTFIELD, "keys")
1003 d.newrefattr(fld, dwarf.DW_AT_type, dwhks)
1004 newmemberoffsetattr(fld, abi.OldMapBucketCount)
1005 fld = d.newdie(dwhb, dwarf.DW_ABRV_STRUCTFIELD, "values")
1006 d.newrefattr(fld, dwarf.DW_AT_type, dwhvs)
1007 newmemberoffsetattr(fld, abi.OldMapBucketCount+abi.OldMapBucketCount*int32(keysize))
1008 fld = d.newdie(dwhb, dwarf.DW_ABRV_STRUCTFIELD, "overflow")
1009 d.newrefattr(fld, dwarf.DW_AT_type, d.defptrto(d.dtolsym(dwhb.Sym)))
1010 newmemberoffsetattr(fld, abi.OldMapBucketCount+abi.OldMapBucketCount*(int32(keysize)+int32(valsize)))
1011 if d.arch.RegSize > d.arch.PtrSize {
1012 fld = d.newdie(dwhb, dwarf.DW_ABRV_STRUCTFIELD, "pad")
1013 d.newrefattr(fld, dwarf.DW_AT_type, d.uintptrInfoSym)
1014 newmemberoffsetattr(fld, abi.OldMapBucketCount+abi.OldMapBucketCount*(int32(keysize)+int32(valsize))+int32(d.arch.PtrSize))
1015 }
1016
1017 newattr(dwhb, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, abi.OldMapBucketCount+abi.OldMapBucketCount*keysize+abi.OldMapBucketCount*valsize+int64(d.arch.RegSize), 0)
1018 })
1019
1020
1021 dwhs := d.mkinternaltype(ctxt, dwarf.DW_ABRV_STRUCTTYPE, "hash", keyname, valname, func(dwh *dwarf.DWDie) {
1022 d.copychildren(ctxt, dwh, hash)
1023 d.substitutetype(dwh, "buckets", d.defptrto(dwhbs))
1024 d.substitutetype(dwh, "oldbuckets", d.defptrto(dwhbs))
1025 newattr(dwh, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, getattr(hash, dwarf.DW_AT_byte_size).Value, nil)
1026 })
1027
1028
1029 d.newrefattr(die, dwarf.DW_AT_type, d.defptrto(dwhs))
1030 }
1031 }
1032
1033 func (d *dwctxt) synthesizechantypes(ctxt *Link, die *dwarf.DWDie) {
1034 sudog := walktypedef(d.findprotodie(ctxt, "type:runtime.sudog"))
1035 waitq := walktypedef(d.findprotodie(ctxt, "type:runtime.waitq"))
1036 hchan := walktypedef(d.findprotodie(ctxt, "type:runtime.hchan"))
1037 if sudog == nil || waitq == nil || hchan == nil {
1038 return
1039 }
1040
1041 sudogsize := int(getattr(sudog, dwarf.DW_AT_byte_size).Value)
1042
1043 for ; die != nil; die = die.Link {
1044 if die.Abbrev != dwarf.DW_ABRV_CHANTYPE {
1045 continue
1046 }
1047 elemgotype := loader.Sym(getattr(die, dwarf.DW_AT_type).Data.(dwSym))
1048 tname := d.ldr.SymName(elemgotype)
1049 elemname := tname[5:]
1050 elemtype := d.walksymtypedef(d.defgotype(d.lookupOrDiag(tname)))
1051
1052
1053 dwss := d.mkinternaltype(ctxt, dwarf.DW_ABRV_STRUCTTYPE, "sudog", elemname, "", func(dws *dwarf.DWDie) {
1054 d.copychildren(ctxt, dws, sudog)
1055 d.substitutetype(dws, "elem", d.defptrto(elemtype))
1056 newattr(dws, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, int64(sudogsize), nil)
1057 })
1058
1059
1060 dwws := d.mkinternaltype(ctxt, dwarf.DW_ABRV_STRUCTTYPE, "waitq", elemname, "", func(dww *dwarf.DWDie) {
1061
1062 d.copychildren(ctxt, dww, waitq)
1063 d.substitutetype(dww, "first", d.defptrto(dwss))
1064 d.substitutetype(dww, "last", d.defptrto(dwss))
1065 newattr(dww, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, getattr(waitq, dwarf.DW_AT_byte_size).Value, nil)
1066 })
1067
1068
1069 dwhs := d.mkinternaltype(ctxt, dwarf.DW_ABRV_STRUCTTYPE, "hchan", elemname, "", func(dwh *dwarf.DWDie) {
1070 d.copychildren(ctxt, dwh, hchan)
1071 d.substitutetype(dwh, "recvq", dwws)
1072 d.substitutetype(dwh, "sendq", dwws)
1073 newattr(dwh, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, getattr(hchan, dwarf.DW_AT_byte_size).Value, nil)
1074 })
1075
1076 d.newrefattr(die, dwarf.DW_AT_type, d.defptrto(dwhs))
1077 }
1078 }
1079
1080
1081
1082 func (d *dwctxt) createUnitLength(su *loader.SymbolBuilder, v uint64) {
1083 if isDwarf64(d.linkctxt) {
1084 su.AddUint32(d.arch, 0xFFFFFFFF)
1085 }
1086 d.addDwarfAddrField(su, v)
1087 }
1088
1089
1090 func (d *dwctxt) addDwarfAddrField(sb *loader.SymbolBuilder, v uint64) {
1091 if isDwarf64(d.linkctxt) {
1092 sb.AddUint(d.arch, v)
1093 } else {
1094 sb.AddUint32(d.arch, uint32(v))
1095 }
1096 }
1097
1098
1099 func (d *dwctxt) addDwarfAddrRef(sb *loader.SymbolBuilder, t loader.Sym) {
1100 if isDwarf64(d.linkctxt) {
1101 d.adddwarfref(sb, t, 8)
1102 } else {
1103 d.adddwarfref(sb, t, 4)
1104 }
1105 }
1106
1107
1108 func (d *dwctxt) calcCompUnitRanges() {
1109 var prevUnit *sym.CompilationUnit
1110 for _, s := range d.linkctxt.Textp {
1111 sym := loader.Sym(s)
1112
1113 fi := d.ldr.FuncInfo(sym)
1114 if !fi.Valid() {
1115 continue
1116 }
1117
1118
1119
1120 unit := d.ldr.SymUnit(sym)
1121 if unit == nil {
1122 continue
1123 }
1124
1125
1126
1127
1128
1129
1130
1131
1132 sval := d.ldr.SymValue(sym)
1133 u0val := d.ldr.SymValue(loader.Sym(unit.Textp[0]))
1134 if prevUnit != unit {
1135 unit.PCs = append(unit.PCs, dwarf.Range{Start: sval - u0val})
1136 prevUnit = unit
1137 }
1138 unit.PCs[len(unit.PCs)-1].End = sval - u0val + int64(len(d.ldr.Data(sym)))
1139 }
1140 }
1141
1142 func movetomodule(ctxt *Link, parent *dwarf.DWDie) {
1143 die := ctxt.runtimeCU.DWInfo.Child
1144 if die == nil {
1145 ctxt.runtimeCU.DWInfo.Child = parent.Child
1146 return
1147 }
1148 for die.Link != nil {
1149 die = die.Link
1150 }
1151 die.Link = parent.Child
1152 }
1153
1154
1158 const (
1159 LINE_BASE = -4
1160 LINE_RANGE = 10
1161 PC_RANGE = (255 - OPCODE_BASE) / LINE_RANGE
1162 OPCODE_BASE = 11
1163 )
1164
1165
1168
1169 func getCompilationDir() string {
1170
1171
1172
1173
1174
1175
1176 return "."
1177 }
1178
1179 func (d *dwctxt) importInfoSymbol(dsym loader.Sym) {
1180 d.ldr.SetAttrReachable(dsym, true)
1181 d.ldr.SetAttrNotInSymbolTable(dsym, true)
1182 dst := d.ldr.SymType(dsym)
1183 if dst != sym.SDWARFCONST && dst != sym.SDWARFABSFCN {
1184 log.Fatalf("error: DWARF info sym %d/%s with incorrect type %s", dsym, d.ldr.SymName(dsym), d.ldr.SymType(dsym).String())
1185 }
1186 relocs := d.ldr.Relocs(dsym)
1187 for i := 0; i < relocs.Count(); i++ {
1188 r := relocs.At(i)
1189 if r.Type() != objabi.R_DWARFSECREF {
1190 continue
1191 }
1192 rsym := r.Sym()
1193
1194
1195 if _, ok := d.rtmap[rsym]; ok {
1196
1197 continue
1198 }
1199
1200
1201 sn := d.ldr.SymName(rsym)
1202 tn := sn[len(dwarf.InfoPrefix):]
1203 ts := d.ldr.Lookup("type:"+tn, 0)
1204 d.defgotype(ts)
1205 }
1206 }
1207
1208 func expandFile(fname string) string {
1209 fname = strings.TrimPrefix(fname, src.FileSymPrefix)
1210 return expandGoroot(fname)
1211 }
1212
1213
1214
1215
1216
1217
1218
1219 func (d *dwctxt) writeDirFileTables(unit *sym.CompilationUnit, lsu *loader.SymbolBuilder) {
1220 type fileDir struct {
1221 base string
1222 dir int
1223 }
1224 dirNums := make(map[string]int)
1225 dirs := []string{""}
1226 files := []fileDir{}
1227
1228
1229
1230 for i, name := range unit.FileTable {
1231 name := expandFile(name)
1232 if len(name) == 0 {
1233
1234
1235 name = fmt.Sprintf("<missing>_%d", i)
1236 }
1237
1238
1239
1240 file := path.Base(name)
1241 dir := path.Dir(name)
1242 dirIdx, ok := dirNums[dir]
1243 if !ok && dir != "." {
1244 dirIdx = len(dirNums) + 1
1245 dirNums[dir] = dirIdx
1246 dirs = append(dirs, dir)
1247 }
1248 files = append(files, fileDir{base: file, dir: dirIdx})
1249
1250
1251
1252
1253 if i := strings.Index(name, "runtime/proc.go"); i >= 0 && unit.Lib.Pkg == "runtime" {
1254 d.dwmu.Lock()
1255 if gdbscript == "" {
1256 k := strings.Index(name, "runtime/proc.go")
1257 gdbscript = name[:k] + "runtime/runtime-gdb.py"
1258 }
1259 d.dwmu.Unlock()
1260 }
1261 }
1262
1263
1264
1265 lsDwsym := dwSym(lsu.Sym())
1266 for k := 1; k < len(dirs); k++ {
1267 d.AddString(lsDwsym, dirs[k])
1268 }
1269 lsu.AddUint8(0)
1270
1271
1272 for k := 0; k < len(files); k++ {
1273 d.AddString(lsDwsym, files[k].base)
1274 dwarf.Uleb128put(d, lsDwsym, int64(files[k].dir))
1275 lsu.AddUint8(0)
1276 lsu.AddUint8(0)
1277 }
1278 lsu.AddUint8(0)
1279 }
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289 func (d *dwctxt) writelines(unit *sym.CompilationUnit, lineProlog loader.Sym) []loader.Sym {
1290 is_stmt := uint8(1)
1291
1292 unitstart := int64(-1)
1293 headerstart := int64(-1)
1294 headerend := int64(-1)
1295
1296 syms := make([]loader.Sym, 0, len(unit.Textp)+2)
1297 syms = append(syms, lineProlog)
1298 lsu := d.ldr.MakeSymbolUpdater(lineProlog)
1299 lsDwsym := dwSym(lineProlog)
1300 newattr(unit.DWInfo, dwarf.DW_AT_stmt_list, dwarf.DW_CLS_PTR, 0, lsDwsym)
1301
1302
1303
1304 unitLengthOffset := lsu.Size()
1305 d.createUnitLength(lsu, 0)
1306 unitstart = lsu.Size()
1307 lsu.AddUint16(d.arch, 2)
1308 headerLengthOffset := lsu.Size()
1309 d.addDwarfAddrField(lsu, 0)
1310 headerstart = lsu.Size()
1311
1312
1313 lsu.AddUint8(1)
1314 lsu.AddUint8(is_stmt)
1315 lsu.AddUint8(LINE_BASE & 0xFF)
1316 lsu.AddUint8(LINE_RANGE)
1317 lsu.AddUint8(OPCODE_BASE)
1318 lsu.AddUint8(0)
1319 lsu.AddUint8(1)
1320 lsu.AddUint8(1)
1321 lsu.AddUint8(1)
1322 lsu.AddUint8(1)
1323 lsu.AddUint8(0)
1324 lsu.AddUint8(0)
1325 lsu.AddUint8(0)
1326 lsu.AddUint8(1)
1327 lsu.AddUint8(0)
1328
1329
1330 d.writeDirFileTables(unit, lsu)
1331
1332
1333 headerend = lsu.Size()
1334 unitlen := lsu.Size() - unitstart
1335
1336
1337 for _, s := range unit.Textp {
1338 fnSym := loader.Sym(s)
1339 _, _, _, lines := d.ldr.GetFuncDwarfAuxSyms(fnSym)
1340
1341
1342 if lines != 0 {
1343 syms = append(syms, lines)
1344 unitlen += int64(len(d.ldr.Data(lines)))
1345 }
1346 }
1347
1348 if d.linkctxt.HeadType == objabi.Haix {
1349 addDwsectCUSize(".debug_line", unit.Lib.Pkg, uint64(unitlen))
1350 }
1351
1352 if isDwarf64(d.linkctxt) {
1353 lsu.SetUint(d.arch, unitLengthOffset+4, uint64(unitlen))
1354 lsu.SetUint(d.arch, headerLengthOffset, uint64(headerend-headerstart))
1355 } else {
1356 lsu.SetUint32(d.arch, unitLengthOffset, uint32(unitlen))
1357 lsu.SetUint32(d.arch, headerLengthOffset, uint32(headerend-headerstart))
1358 }
1359
1360 return syms
1361 }
1362
1363
1364
1365
1366 func (d *dwctxt) writepcranges(unit *sym.CompilationUnit, base loader.Sym, pcs []dwarf.Range, rangeProlog loader.Sym) []loader.Sym {
1367
1368 syms := make([]loader.Sym, 0, len(unit.RangeSyms)+1)
1369 syms = append(syms, rangeProlog)
1370 rsu := d.ldr.MakeSymbolUpdater(rangeProlog)
1371 rDwSym := dwSym(rangeProlog)
1372
1373
1374 newattr(unit.DWInfo, dwarf.DW_AT_ranges, dwarf.DW_CLS_PTR, rsu.Size(), rDwSym)
1375 newattr(unit.DWInfo, dwarf.DW_AT_low_pc, dwarf.DW_CLS_ADDRESS, 0, dwSym(base))
1376 dwarf.PutBasedRanges(d, rDwSym, pcs)
1377
1378
1379 rsize := uint64(rsu.Size())
1380 for _, ls := range unit.RangeSyms {
1381 s := loader.Sym(ls)
1382 syms = append(syms, s)
1383 rsize += uint64(d.ldr.SymSize(s))
1384 }
1385
1386 if d.linkctxt.HeadType == objabi.Haix {
1387 addDwsectCUSize(".debug_ranges", unit.Lib.Pkg, rsize)
1388 }
1389
1390 return syms
1391 }
1392
1393
1396 const (
1397 dataAlignmentFactor = -4
1398 )
1399
1400
1401 func appendPCDeltaCFA(arch *sys.Arch, b []byte, deltapc, cfa int64) []byte {
1402 b = append(b, dwarf.DW_CFA_def_cfa_offset_sf)
1403 b = dwarf.AppendSleb128(b, cfa/dataAlignmentFactor)
1404
1405 switch {
1406 case deltapc < 0x40:
1407 b = append(b, uint8(dwarf.DW_CFA_advance_loc+deltapc))
1408 case deltapc < 0x100:
1409 b = append(b, dwarf.DW_CFA_advance_loc1)
1410 b = append(b, uint8(deltapc))
1411 case deltapc < 0x10000:
1412 b = append(b, dwarf.DW_CFA_advance_loc2, 0, 0)
1413 arch.ByteOrder.PutUint16(b[len(b)-2:], uint16(deltapc))
1414 default:
1415 b = append(b, dwarf.DW_CFA_advance_loc4, 0, 0, 0, 0)
1416 arch.ByteOrder.PutUint32(b[len(b)-4:], uint32(deltapc))
1417 }
1418 return b
1419 }
1420
1421 func (d *dwctxt) writeframes(fs loader.Sym) dwarfSecInfo {
1422 fsd := dwSym(fs)
1423 fsu := d.ldr.MakeSymbolUpdater(fs)
1424 fsu.SetType(sym.SDWARFSECT)
1425 isdw64 := isDwarf64(d.linkctxt)
1426 haslr := d.linkctxt.Arch.HasLR
1427
1428
1429 lengthFieldSize := int64(4)
1430 if isdw64 {
1431 lengthFieldSize += 8
1432 }
1433
1434
1435 cieReserve := uint32(16)
1436 if haslr {
1437 cieReserve = 32
1438 }
1439 if isdw64 {
1440 cieReserve += 4
1441 }
1442 d.createUnitLength(fsu, uint64(cieReserve))
1443 d.addDwarfAddrField(fsu, ^uint64(0))
1444 fsu.AddUint8(3)
1445 fsu.AddUint8(0)
1446 dwarf.Uleb128put(d, fsd, 1)
1447 dwarf.Sleb128put(d, fsd, dataAlignmentFactor)
1448 dwarf.Uleb128put(d, fsd, int64(thearch.Dwarfreglr))
1449
1450 fsu.AddUint8(dwarf.DW_CFA_def_cfa)
1451 dwarf.Uleb128put(d, fsd, int64(thearch.Dwarfregsp))
1452 if haslr {
1453 dwarf.Uleb128put(d, fsd, int64(0))
1454
1455 fsu.AddUint8(dwarf.DW_CFA_same_value)
1456 dwarf.Uleb128put(d, fsd, int64(thearch.Dwarfreglr))
1457
1458 fsu.AddUint8(dwarf.DW_CFA_val_offset)
1459 dwarf.Uleb128put(d, fsd, int64(thearch.Dwarfregsp))
1460 dwarf.Uleb128put(d, fsd, int64(0))
1461 } else {
1462 dwarf.Uleb128put(d, fsd, int64(d.arch.PtrSize))
1463
1464 fsu.AddUint8(dwarf.DW_CFA_offset_extended)
1465 dwarf.Uleb128put(d, fsd, int64(thearch.Dwarfreglr))
1466 dwarf.Uleb128put(d, fsd, int64(-d.arch.PtrSize)/dataAlignmentFactor)
1467 }
1468
1469 pad := int64(cieReserve) + lengthFieldSize - int64(len(d.ldr.Data(fs)))
1470
1471 if pad < 0 {
1472 Exitf("dwarf: cieReserve too small by %d bytes.", -pad)
1473 }
1474
1475 internalExec := d.linkctxt.BuildMode == BuildModeExe && d.linkctxt.IsInternal()
1476 addAddrPlus := loader.GenAddAddrPlusFunc(internalExec)
1477
1478 fsu.AddBytes(zeros[:pad])
1479
1480 var deltaBuf []byte
1481 pcsp := obj.NewPCIter(uint32(d.arch.MinLC))
1482 for _, s := range d.linkctxt.Textp {
1483 fn := loader.Sym(s)
1484 fi := d.ldr.FuncInfo(fn)
1485 if !fi.Valid() {
1486 continue
1487 }
1488 fpcsp := d.ldr.Pcsp(s)
1489
1490
1491
1492 deltaBuf = deltaBuf[:0]
1493 if haslr && fi.TopFrame() {
1494
1495
1496
1497 deltaBuf = append(deltaBuf, dwarf.DW_CFA_undefined)
1498 deltaBuf = dwarf.AppendUleb128(deltaBuf, uint64(thearch.Dwarfreglr))
1499 }
1500
1501 for pcsp.Init(d.linkctxt.loader.Data(fpcsp)); !pcsp.Done; pcsp.Next() {
1502 nextpc := pcsp.NextPC
1503
1504
1505
1506 if int64(nextpc) == int64(len(d.ldr.Data(fn))) {
1507 nextpc--
1508 if nextpc < pcsp.PC {
1509 continue
1510 }
1511 }
1512
1513 spdelta := int64(pcsp.Value)
1514 if !haslr {
1515
1516 spdelta += int64(d.arch.PtrSize)
1517 }
1518
1519 if haslr && !fi.TopFrame() {
1520
1521
1522
1523 if pcsp.Value > 0 {
1524
1525
1526 deltaBuf = append(deltaBuf, dwarf.DW_CFA_offset_extended_sf)
1527 deltaBuf = dwarf.AppendUleb128(deltaBuf, uint64(thearch.Dwarfreglr))
1528 deltaBuf = dwarf.AppendSleb128(deltaBuf, -spdelta/dataAlignmentFactor)
1529 } else {
1530
1531
1532 deltaBuf = append(deltaBuf, dwarf.DW_CFA_same_value)
1533 deltaBuf = dwarf.AppendUleb128(deltaBuf, uint64(thearch.Dwarfreglr))
1534 }
1535 }
1536
1537 deltaBuf = appendPCDeltaCFA(d.arch, deltaBuf, int64(nextpc)-int64(pcsp.PC), spdelta)
1538 }
1539 pad := int(Rnd(int64(len(deltaBuf)), int64(d.arch.PtrSize))) - len(deltaBuf)
1540 deltaBuf = append(deltaBuf, zeros[:pad]...)
1541
1542
1543
1544
1545
1546
1547
1548 fdeLength := uint64(4 + 2*d.arch.PtrSize + len(deltaBuf))
1549 if isdw64 {
1550 fdeLength += 4
1551 }
1552 d.createUnitLength(fsu, fdeLength)
1553
1554 if d.linkctxt.LinkMode == LinkExternal {
1555 d.addDwarfAddrRef(fsu, fs)
1556 } else {
1557 d.addDwarfAddrField(fsu, 0)
1558 }
1559 addAddrPlus(fsu, d.arch, s, 0)
1560 fsu.AddUintXX(d.arch, uint64(len(d.ldr.Data(fn))), d.arch.PtrSize)
1561 fsu.AddBytes(deltaBuf)
1562
1563 if d.linkctxt.HeadType == objabi.Haix {
1564 addDwsectCUSize(".debug_frame", d.ldr.SymPkg(fn), fdeLength+uint64(lengthFieldSize))
1565 }
1566 }
1567
1568 return dwarfSecInfo{syms: []loader.Sym{fs}}
1569 }
1570
1571
1574
1575 const (
1576 COMPUNITHEADERSIZE = 4 + 2 + 4 + 1
1577 )
1578
1579 func (d *dwctxt) writeUnitInfo(u *sym.CompilationUnit, abbrevsym loader.Sym, infoEpilog loader.Sym) []loader.Sym {
1580 syms := []loader.Sym{}
1581 if len(u.Textp) == 0 && u.DWInfo.Child == nil && len(u.VarDIEs) == 0 {
1582 return syms
1583 }
1584
1585 compunit := u.DWInfo
1586 s := d.dtolsym(compunit.Sym)
1587 su := d.ldr.MakeSymbolUpdater(s)
1588
1589
1590
1591
1592 d.createUnitLength(su, 0)
1593 su.AddUint16(d.arch, 4)
1594
1595
1596 d.addDwarfAddrRef(su, abbrevsym)
1597
1598 su.AddUint8(uint8(d.arch.PtrSize))
1599
1600 ds := dwSym(s)
1601 dwarf.Uleb128put(d, ds, int64(compunit.Abbrev))
1602 dwarf.PutAttrs(d, ds, compunit.Abbrev, compunit.Attr)
1603
1604
1605 cu := make([]loader.Sym, 0, len(u.AbsFnDIEs)+len(u.FuncDIEs))
1606 cu = append(cu, s)
1607 cu = append(cu, u.AbsFnDIEs...)
1608 cu = append(cu, u.FuncDIEs...)
1609 if u.Consts != 0 {
1610 cu = append(cu, loader.Sym(u.Consts))
1611 }
1612 cu = append(cu, u.VarDIEs...)
1613 var cusize int64
1614 for _, child := range cu {
1615 cusize += int64(len(d.ldr.Data(child)))
1616 }
1617
1618 for die := compunit.Child; die != nil; die = die.Link {
1619 l := len(cu)
1620 lastSymSz := int64(len(d.ldr.Data(cu[l-1])))
1621 cu = d.putdie(cu, die)
1622 if lastSymSz != int64(len(d.ldr.Data(cu[l-1]))) {
1623
1624 cusize = cusize - lastSymSz + int64(len(d.ldr.Data(cu[l-1])))
1625 }
1626 for _, child := range cu[l:] {
1627 cusize += int64(len(d.ldr.Data(child)))
1628 }
1629 }
1630
1631 culu := d.ldr.MakeSymbolUpdater(infoEpilog)
1632 culu.AddUint8(0)
1633 cu = append(cu, infoEpilog)
1634 cusize++
1635
1636
1637 if d.linkctxt.HeadType == objabi.Haix {
1638 addDwsectCUSize(".debug_info", d.getPkgFromCUSym(s), uint64(cusize))
1639 }
1640 if isDwarf64(d.linkctxt) {
1641 cusize -= 12
1642 su.SetUint(d.arch, 4, uint64(cusize))
1643 } else {
1644 cusize -= 4
1645 su.SetUint32(d.arch, 0, uint32(cusize))
1646 }
1647 return append(syms, cu...)
1648 }
1649
1650 func (d *dwctxt) writegdbscript() dwarfSecInfo {
1651
1652 if d.linkctxt.HeadType == objabi.Haix {
1653 return dwarfSecInfo{}
1654 }
1655 if d.linkctxt.LinkMode == LinkExternal && d.linkctxt.HeadType == objabi.Hwindows && d.linkctxt.BuildMode == BuildModeCArchive {
1656
1657
1658
1659
1660
1661
1662 return dwarfSecInfo{}
1663 }
1664 if gdbscript == "" {
1665 return dwarfSecInfo{}
1666 }
1667
1668 gs := d.ldr.CreateSymForUpdate(".debug_gdb_scripts", 0)
1669 gs.SetType(sym.SDWARFSECT)
1670
1671 gs.AddUint8(GdbScriptPythonFileId)
1672 gs.Addstring(gdbscript)
1673 return dwarfSecInfo{syms: []loader.Sym{gs.Sym()}}
1674 }
1675
1676
1677
1678
1679 var prototypedies map[string]*dwarf.DWDie
1680
1681 func dwarfEnabled(ctxt *Link) bool {
1682 if *FlagW {
1683 return false
1684 }
1685 if ctxt.HeadType == objabi.Hplan9 || ctxt.HeadType == objabi.Hjs || ctxt.HeadType == objabi.Hwasip1 {
1686 return false
1687 }
1688
1689 if ctxt.LinkMode == LinkExternal {
1690 switch {
1691 case ctxt.IsELF:
1692 case ctxt.HeadType == objabi.Hdarwin:
1693 case ctxt.HeadType == objabi.Hwindows:
1694 case ctxt.HeadType == objabi.Haix:
1695 res, err := dwarf.IsDWARFEnabledOnAIXLd(ctxt.extld())
1696 if err != nil {
1697 Exitf("%v", err)
1698 }
1699 return res
1700 default:
1701 return false
1702 }
1703 }
1704
1705 return true
1706 }
1707
1708
1709
1710 func (d *dwctxt) mkBuiltinType(ctxt *Link, abrv int, tname string) *dwarf.DWDie {
1711
1712 die := d.newdie(&dwtypes, abrv, tname)
1713
1714
1715 gotype := d.lookupOrDiag("type:" + tname)
1716
1717
1718 ds := loader.Sym(die.Sym.(dwSym))
1719 d.rtmap[ds] = gotype
1720
1721
1722 d.tdmap[gotype] = ds
1723
1724 return die
1725 }
1726
1727
1728
1729
1730 func (d *dwctxt) dwarfVisitFunction(fnSym loader.Sym, unit *sym.CompilationUnit) {
1731
1732
1733
1734 infosym, _, rangesym, _ := d.ldr.GetFuncDwarfAuxSyms(fnSym)
1735 if infosym == 0 {
1736 return
1737 }
1738 d.ldr.SetAttrNotInSymbolTable(infosym, true)
1739 d.ldr.SetAttrReachable(infosym, true)
1740 unit.FuncDIEs = append(unit.FuncDIEs, sym.LoaderSym(infosym))
1741 if rangesym != 0 {
1742 d.ldr.SetAttrNotInSymbolTable(rangesym, true)
1743 d.ldr.SetAttrReachable(rangesym, true)
1744 unit.RangeSyms = append(unit.RangeSyms, sym.LoaderSym(rangesym))
1745 }
1746
1747
1748
1749
1750
1751 drelocs := d.ldr.Relocs(infosym)
1752 for ri := 0; ri < drelocs.Count(); ri++ {
1753 r := drelocs.At(ri)
1754
1755 if r.Type() == objabi.R_USETYPE {
1756 d.defgotype(r.Sym())
1757 continue
1758 }
1759 if r.Type() != objabi.R_DWARFSECREF {
1760 continue
1761 }
1762
1763 rsym := r.Sym()
1764 rst := d.ldr.SymType(rsym)
1765
1766
1767 if rst == sym.SDWARFABSFCN {
1768 if !d.ldr.AttrOnList(rsym) {
1769
1770 d.ldr.SetAttrOnList(rsym, true)
1771 unit.AbsFnDIEs = append(unit.AbsFnDIEs, sym.LoaderSym(rsym))
1772 d.importInfoSymbol(rsym)
1773 }
1774 continue
1775 }
1776
1777
1778 if rst != sym.SDWARFTYPE && rst != sym.Sxxx {
1779 continue
1780 }
1781 if _, ok := d.rtmap[rsym]; ok {
1782
1783 continue
1784 }
1785
1786 rsn := d.ldr.SymName(rsym)
1787 tn := rsn[len(dwarf.InfoPrefix):]
1788 ts := d.ldr.Lookup("type:"+tn, 0)
1789 d.defgotype(ts)
1790 }
1791 }
1792
1793
1794
1795
1796
1797
1798
1799
1800 func dwarfGenerateDebugInfo(ctxt *Link) {
1801 if !dwarfEnabled(ctxt) {
1802 return
1803 }
1804
1805 d := &dwctxt{
1806 linkctxt: ctxt,
1807 ldr: ctxt.loader,
1808 arch: ctxt.Arch,
1809 tmap: make(map[string]loader.Sym),
1810 tdmap: make(map[loader.Sym]loader.Sym),
1811 rtmap: make(map[loader.Sym]loader.Sym),
1812 }
1813 d.typeRuntimeEface = d.lookupOrDiag("type:runtime.eface")
1814 d.typeRuntimeIface = d.lookupOrDiag("type:runtime.iface")
1815
1816 if ctxt.HeadType == objabi.Haix {
1817
1818 dwsectCUSize = make(map[string]uint64)
1819 }
1820
1821
1822 newattr(&dwtypes, dwarf.DW_AT_name, dwarf.DW_CLS_STRING, int64(len("dwtypes")), "dwtypes")
1823
1824
1825 d.newdie(&dwtypes, dwarf.DW_ABRV_NULLTYPE, "<unspecified>")
1826
1827
1828
1829 unsafeptrDie := d.mkBuiltinType(ctxt, dwarf.DW_ABRV_BARE_PTRTYPE, "unsafe.Pointer")
1830 newattr(unsafeptrDie, dwarf.DW_AT_go_runtime_type, dwarf.DW_CLS_GO_TYPEREF, 0, dwSym(d.lookupOrDiag("type:unsafe.Pointer")))
1831 uintptrDie := d.mkBuiltinType(ctxt, dwarf.DW_ABRV_BASETYPE, "uintptr")
1832 newattr(uintptrDie, dwarf.DW_AT_encoding, dwarf.DW_CLS_CONSTANT, dwarf.DW_ATE_unsigned, 0)
1833 newattr(uintptrDie, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, int64(d.arch.PtrSize), 0)
1834 newattr(uintptrDie, dwarf.DW_AT_go_kind, dwarf.DW_CLS_CONSTANT, int64(abi.Uintptr), 0)
1835 newattr(uintptrDie, dwarf.DW_AT_go_runtime_type, dwarf.DW_CLS_GO_TYPEREF, 0, dwSym(d.lookupOrDiag("type:uintptr")))
1836
1837 d.uintptrInfoSym = d.mustFind("uintptr")
1838
1839
1840 prototypedies = map[string]*dwarf.DWDie{
1841 "type:runtime.stringStructDWARF": nil,
1842 "type:runtime.slice": nil,
1843 "type:runtime.sudog": nil,
1844 "type:runtime.waitq": nil,
1845 "type:runtime.hchan": nil,
1846 }
1847 if buildcfg.Experiment.SwissMap {
1848 prototypedies["type:internal/runtime/maps.Map"] = nil
1849 prototypedies["type:internal/runtime/maps.table"] = nil
1850 prototypedies["type:internal/runtime/maps.groupsReference"] = nil
1851 } else {
1852 prototypedies["type:runtime.hmap"] = nil
1853 prototypedies["type:runtime.bmap"] = nil
1854 }
1855
1856
1857 for _, typ := range []string{
1858 "type:internal/abi.Type",
1859 "type:internal/abi.ArrayType",
1860 "type:internal/abi.ChanType",
1861 "type:internal/abi.FuncType",
1862 "type:internal/abi.PtrType",
1863 "type:internal/abi.SliceType",
1864 "type:internal/abi.StructType",
1865 "type:internal/abi.InterfaceType",
1866 "type:internal/abi.ITab",
1867 "type:internal/abi.Imethod"} {
1868 d.defgotype(d.lookupOrDiag(typ))
1869 }
1870 if buildcfg.Experiment.SwissMap {
1871 d.defgotype(d.lookupOrDiag("type:internal/abi.SwissMapType"))
1872 } else {
1873 d.defgotype(d.lookupOrDiag("type:internal/abi.OldMapType"))
1874 }
1875
1876
1877 var dwroot dwarf.DWDie
1878 flagVariants := make(map[string]bool)
1879
1880 for _, lib := range ctxt.Library {
1881
1882 consts := d.ldr.Lookup(dwarf.ConstInfoPrefix+lib.Pkg, 0)
1883 for _, unit := range lib.Units {
1884
1885 if consts != 0 {
1886 unit.Consts = sym.LoaderSym(consts)
1887 d.importInfoSymbol(consts)
1888 consts = 0
1889 }
1890 ctxt.compUnits = append(ctxt.compUnits, unit)
1891
1892
1893 if unit.Lib.Pkg == "runtime" {
1894 ctxt.runtimeCU = unit
1895 }
1896
1897 cuabrv := dwarf.DW_ABRV_COMPUNIT
1898 if len(unit.Textp) == 0 {
1899 cuabrv = dwarf.DW_ABRV_COMPUNIT_TEXTLESS
1900 }
1901 unit.DWInfo = d.newdie(&dwroot, cuabrv, unit.Lib.Pkg)
1902 newattr(unit.DWInfo, dwarf.DW_AT_language, dwarf.DW_CLS_CONSTANT, int64(dwarf.DW_LANG_Go), 0)
1903
1904 compDir := getCompilationDir()
1905
1906
1907
1908 newattr(unit.DWInfo, dwarf.DW_AT_comp_dir, dwarf.DW_CLS_STRING, int64(len(compDir)), compDir)
1909
1910 var peData []byte
1911 if producerExtra := d.ldr.Lookup(dwarf.CUInfoPrefix+"producer."+unit.Lib.Pkg, 0); producerExtra != 0 {
1912 peData = d.ldr.Data(producerExtra)
1913 }
1914 producer := "Go cmd/compile " + buildcfg.Version
1915 if len(peData) > 0 {
1916
1917
1918
1919
1920
1921
1922 producer += "; " + string(peData)
1923 flagVariants[string(peData)] = true
1924 } else {
1925 flagVariants[""] = true
1926 }
1927
1928 newattr(unit.DWInfo, dwarf.DW_AT_producer, dwarf.DW_CLS_STRING, int64(len(producer)), producer)
1929
1930 var pkgname string
1931 if pnSymIdx := d.ldr.Lookup(dwarf.CUInfoPrefix+"packagename."+unit.Lib.Pkg, 0); pnSymIdx != 0 {
1932 pnsData := d.ldr.Data(pnSymIdx)
1933 pkgname = string(pnsData)
1934 }
1935 newattr(unit.DWInfo, dwarf.DW_AT_go_package_name, dwarf.DW_CLS_STRING, int64(len(pkgname)), pkgname)
1936
1937
1938
1939
1940
1941 for _, s := range unit.Textp {
1942 d.dwarfVisitFunction(loader.Sym(s), unit)
1943 }
1944 }
1945 }
1946
1947
1948
1949
1950 if checkStrictDups > 1 && len(flagVariants) > 1 {
1951 checkStrictDups = 1
1952 }
1953
1954
1955
1956
1957
1958
1959
1960
1961 for idx := loader.Sym(1); idx < loader.Sym(d.ldr.NDef()); idx++ {
1962 if !d.ldr.AttrReachable(idx) ||
1963 d.ldr.AttrNotInSymbolTable(idx) ||
1964 d.ldr.SymVersion(idx) >= sym.SymVerStatic {
1965 continue
1966 }
1967 t := d.ldr.SymType(idx)
1968 switch {
1969 case t.IsRODATA(), t.IsDATA(), t.IsNOPTRDATA(),
1970 t == sym.STYPE, t == sym.SBSS, t == sym.SNOPTRBSS, t == sym.STLSBSS:
1971
1972 default:
1973 continue
1974 }
1975
1976 gt := d.ldr.SymGoType(idx)
1977 if gt == 0 {
1978 if t == sym.SRODATA {
1979 if d.ldr.IsDict(idx) {
1980
1981 relocs := d.ldr.Relocs(idx)
1982 for i := 0; i < relocs.Count(); i++ {
1983 reloc := relocs.At(i)
1984 if reloc.Type() == objabi.R_USEIFACE {
1985 d.defgotype(reloc.Sym())
1986 }
1987 }
1988 }
1989 }
1990 continue
1991 }
1992
1993
1994 if d.ldr.IsFileLocal(idx) {
1995 continue
1996 }
1997
1998
1999
2000
2001
2002
2003 varDIE := d.ldr.GetVarDwarfAuxSym(idx)
2004 if varDIE != 0 {
2005 unit := d.ldr.SymUnit(idx)
2006 d.defgotype(gt)
2007 unit.VarDIEs = append(unit.VarDIEs, sym.LoaderSym(varDIE))
2008 }
2009 }
2010
2011 d.synthesizestringtypes(ctxt, dwtypes.Child)
2012 d.synthesizeslicetypes(ctxt, dwtypes.Child)
2013 d.synthesizemaptypes(ctxt, dwtypes.Child)
2014 d.synthesizechantypes(ctxt, dwtypes.Child)
2015 }
2016
2017
2018
2019
2020 func dwarfGenerateDebugSyms(ctxt *Link) {
2021 if !dwarfEnabled(ctxt) {
2022 return
2023 }
2024 d := &dwctxt{
2025 linkctxt: ctxt,
2026 ldr: ctxt.loader,
2027 arch: ctxt.Arch,
2028 dwmu: new(sync.Mutex),
2029 }
2030 d.dwarfGenerateDebugSyms()
2031 }
2032
2033
2034
2035 type dwUnitSyms struct {
2036
2037 lineProlog loader.Sym
2038 rangeProlog loader.Sym
2039 infoEpilog loader.Sym
2040
2041
2042 linesyms []loader.Sym
2043 infosyms []loader.Sym
2044 locsyms []loader.Sym
2045 rangessyms []loader.Sym
2046 }
2047
2048
2049
2050
2051
2052
2053 func (d *dwctxt) dwUnitPortion(u *sym.CompilationUnit, abbrevsym loader.Sym, us *dwUnitSyms) {
2054 if u.DWInfo.Abbrev != dwarf.DW_ABRV_COMPUNIT_TEXTLESS {
2055 us.linesyms = d.writelines(u, us.lineProlog)
2056 base := loader.Sym(u.Textp[0])
2057 us.rangessyms = d.writepcranges(u, base, u.PCs, us.rangeProlog)
2058 us.locsyms = d.collectUnitLocs(u)
2059 }
2060 us.infosyms = d.writeUnitInfo(u, abbrevsym, us.infoEpilog)
2061 }
2062
2063 func (d *dwctxt) dwarfGenerateDebugSyms() {
2064 abbrevSec := d.writeabbrev()
2065 dwarfp = append(dwarfp, abbrevSec)
2066 d.calcCompUnitRanges()
2067 slices.SortFunc(d.linkctxt.compUnits, compilationUnitByStartPCCmp)
2068
2069
2070
2071
2072 for _, u := range d.linkctxt.compUnits {
2073 reversetree(&u.DWInfo.Child)
2074 }
2075 reversetree(&dwtypes.Child)
2076 movetomodule(d.linkctxt, &dwtypes)
2077
2078 mkSecSym := func(name string) loader.Sym {
2079 s := d.ldr.CreateSymForUpdate(name, 0)
2080 s.SetType(sym.SDWARFSECT)
2081 s.SetReachable(true)
2082 return s.Sym()
2083 }
2084 mkAnonSym := func(kind sym.SymKind) loader.Sym {
2085 s := d.ldr.MakeSymbolUpdater(d.ldr.CreateExtSym("", 0))
2086 s.SetType(kind)
2087 s.SetReachable(true)
2088 return s.Sym()
2089 }
2090
2091
2092 frameSym := mkSecSym(".debug_frame")
2093 locSym := mkSecSym(".debug_loc")
2094 lineSym := mkSecSym(".debug_line")
2095 rangesSym := mkSecSym(".debug_ranges")
2096 infoSym := mkSecSym(".debug_info")
2097
2098
2099 lineSec := dwarfSecInfo{syms: []loader.Sym{lineSym}}
2100 locSec := dwarfSecInfo{syms: []loader.Sym{locSym}}
2101 rangesSec := dwarfSecInfo{syms: []loader.Sym{rangesSym}}
2102 frameSec := dwarfSecInfo{syms: []loader.Sym{frameSym}}
2103 infoSec := dwarfSecInfo{syms: []loader.Sym{infoSym}}
2104
2105
2106
2107 ncu := len(d.linkctxt.compUnits)
2108 unitSyms := make([]dwUnitSyms, ncu)
2109 for i := 0; i < ncu; i++ {
2110 us := &unitSyms[i]
2111 us.lineProlog = mkAnonSym(sym.SDWARFLINES)
2112 us.rangeProlog = mkAnonSym(sym.SDWARFRANGE)
2113 us.infoEpilog = mkAnonSym(sym.SDWARFFCN)
2114 }
2115
2116 var wg sync.WaitGroup
2117 sema := make(chan struct{}, runtime.GOMAXPROCS(0))
2118
2119
2120
2121 wg.Add(1)
2122 go func() {
2123 sema <- struct{}{}
2124 defer func() {
2125 <-sema
2126 wg.Done()
2127 }()
2128 frameSec = d.writeframes(frameSym)
2129 }()
2130
2131
2132
2133
2134 wg.Add(len(d.linkctxt.compUnits))
2135 for i := 0; i < ncu; i++ {
2136 go func(u *sym.CompilationUnit, us *dwUnitSyms) {
2137 sema <- struct{}{}
2138 defer func() {
2139 <-sema
2140 wg.Done()
2141 }()
2142 d.dwUnitPortion(u, abbrevSec.secSym(), us)
2143 }(d.linkctxt.compUnits[i], &unitSyms[i])
2144 }
2145 wg.Wait()
2146
2147 markReachable := func(syms []loader.Sym) []loader.Sym {
2148 for _, s := range syms {
2149 d.ldr.SetAttrNotInSymbolTable(s, true)
2150 d.ldr.SetAttrReachable(s, true)
2151 }
2152 return syms
2153 }
2154
2155
2156 for i := 0; i < ncu; i++ {
2157 r := &unitSyms[i]
2158 lineSec.syms = append(lineSec.syms, markReachable(r.linesyms)...)
2159 infoSec.syms = append(infoSec.syms, markReachable(r.infosyms)...)
2160 locSec.syms = append(locSec.syms, markReachable(r.locsyms)...)
2161 rangesSec.syms = append(rangesSec.syms, markReachable(r.rangessyms)...)
2162 }
2163 dwarfp = append(dwarfp, lineSec)
2164 dwarfp = append(dwarfp, frameSec)
2165 gdbScriptSec := d.writegdbscript()
2166 if gdbScriptSec.secSym() != 0 {
2167 dwarfp = append(dwarfp, gdbScriptSec)
2168 }
2169 dwarfp = append(dwarfp, infoSec)
2170 if len(locSec.syms) > 1 {
2171 dwarfp = append(dwarfp, locSec)
2172 }
2173 dwarfp = append(dwarfp, rangesSec)
2174
2175
2176
2177
2178
2179 seen := loader.MakeBitmap(d.ldr.NSym())
2180 for _, s := range infoSec.syms {
2181 if seen.Has(s) {
2182 log.Fatalf("dwarf symbol %s listed multiple times",
2183 d.ldr.SymName(s))
2184 }
2185 seen.Set(s)
2186 }
2187 }
2188
2189 func (d *dwctxt) collectUnitLocs(u *sym.CompilationUnit) []loader.Sym {
2190 syms := []loader.Sym{}
2191 for _, fn := range u.FuncDIEs {
2192 relocs := d.ldr.Relocs(loader.Sym(fn))
2193 for i := 0; i < relocs.Count(); i++ {
2194 reloc := relocs.At(i)
2195 if reloc.Type() != objabi.R_DWARFSECREF {
2196 continue
2197 }
2198 rsym := reloc.Sym()
2199 if d.ldr.SymType(rsym) == sym.SDWARFLOC {
2200 syms = append(syms, rsym)
2201
2202 break
2203 }
2204 }
2205 }
2206 return syms
2207 }
2208
2209
2210
2211 func dwarfaddshstrings(ctxt *Link, add func(string)) {
2212 if *FlagW {
2213 return
2214 }
2215
2216 secs := []string{"abbrev", "frame", "info", "loc", "line", "gdb_scripts", "ranges"}
2217 for _, sec := range secs {
2218 add(".debug_" + sec)
2219 if ctxt.IsExternal() {
2220 add(elfRelType + ".debug_" + sec)
2221 }
2222 }
2223 }
2224
2225 func dwarfaddelfsectionsyms(ctxt *Link) {
2226 if *FlagW {
2227 return
2228 }
2229 if ctxt.LinkMode != LinkExternal {
2230 return
2231 }
2232
2233 ldr := ctxt.loader
2234 for _, si := range dwarfp {
2235 s := si.secSym()
2236 sect := ldr.SymSect(si.secSym())
2237 putelfsectionsym(ctxt, ctxt.Out, s, sect.Elfsect.(*ElfShdr).shnum)
2238 }
2239 }
2240
2241
2242
2243
2244 func dwarfcompress(ctxt *Link) {
2245
2246 type compressedSect struct {
2247 index int
2248 compressed []byte
2249 syms []loader.Sym
2250 }
2251
2252 supported := ctxt.IsELF || ctxt.IsWindows() || ctxt.IsDarwin()
2253 if !ctxt.compressDWARF || !supported || ctxt.IsExternal() {
2254 return
2255 }
2256
2257 var compressedCount int
2258 resChannel := make(chan compressedSect)
2259 for i := range dwarfp {
2260 go func(resIndex int, syms []loader.Sym) {
2261 resChannel <- compressedSect{resIndex, compressSyms(ctxt, syms), syms}
2262 }(compressedCount, dwarfp[i].syms)
2263 compressedCount++
2264 }
2265 res := make([]compressedSect, compressedCount)
2266 for ; compressedCount > 0; compressedCount-- {
2267 r := <-resChannel
2268 res[r.index] = r
2269 }
2270
2271 ldr := ctxt.loader
2272 var newDwarfp []dwarfSecInfo
2273 Segdwarf.Sections = Segdwarf.Sections[:0]
2274 for _, z := range res {
2275 s := z.syms[0]
2276 if z.compressed == nil {
2277
2278 ds := dwarfSecInfo{syms: z.syms}
2279 newDwarfp = append(newDwarfp, ds)
2280 Segdwarf.Sections = append(Segdwarf.Sections, ldr.SymSect(s))
2281 } else {
2282 var compressedSegName string
2283 if ctxt.IsELF {
2284 compressedSegName = ldr.SymSect(s).Name
2285 } else {
2286 compressedSegName = ".zdebug_" + ldr.SymSect(s).Name[len(".debug_"):]
2287 }
2288 sect := addsection(ctxt.loader, ctxt.Arch, &Segdwarf, compressedSegName, 04)
2289 sect.Align = int32(ctxt.Arch.Alignment)
2290 sect.Length = uint64(len(z.compressed))
2291 sect.Compressed = true
2292 newSym := ldr.MakeSymbolBuilder(compressedSegName)
2293 ldr.SetAttrReachable(s, true)
2294 newSym.SetData(z.compressed)
2295 newSym.SetSize(int64(len(z.compressed)))
2296 ldr.SetSymSect(newSym.Sym(), sect)
2297 ds := dwarfSecInfo{syms: []loader.Sym{newSym.Sym()}}
2298 newDwarfp = append(newDwarfp, ds)
2299
2300
2301 for _, s := range z.syms {
2302 ldr.SetAttrReachable(s, false)
2303 ldr.FreeSym(s)
2304 }
2305 }
2306 }
2307 dwarfp = newDwarfp
2308
2309
2310
2311
2312 pos := Segdwarf.Vaddr
2313 var prevSect *sym.Section
2314 for _, si := range dwarfp {
2315 for _, s := range si.syms {
2316 ldr.SetSymValue(s, int64(pos))
2317 sect := ldr.SymSect(s)
2318 if sect != prevSect {
2319 sect.Vaddr = uint64(pos)
2320 prevSect = sect
2321 }
2322 if ldr.SubSym(s) != 0 {
2323 log.Fatalf("%s: unexpected sub-symbols", ldr.SymName(s))
2324 }
2325 pos += uint64(ldr.SymSize(s))
2326 if ctxt.IsWindows() {
2327 pos = uint64(Rnd(int64(pos), PEFILEALIGN))
2328 }
2329 }
2330 }
2331 Segdwarf.Length = pos - Segdwarf.Vaddr
2332 }
2333
2334 func compilationUnitByStartPCCmp(a, b *sym.CompilationUnit) int {
2335 switch {
2336 case len(a.Textp) == 0 && len(b.Textp) == 0:
2337 return strings.Compare(a.Lib.Pkg, b.Lib.Pkg)
2338 case len(a.Textp) != 0 && len(b.Textp) == 0:
2339 return -1
2340 case len(a.Textp) == 0 && len(b.Textp) != 0:
2341 return +1
2342 default:
2343 return cmp.Compare(a.PCs[0].Start, b.PCs[0].Start)
2344 }
2345 }
2346
2347
2348
2349
2350
2351 func (d *dwctxt) getPkgFromCUSym(s loader.Sym) string {
2352 return strings.TrimPrefix(d.ldr.SymName(s), dwarf.InfoPrefix+".pkg.")
2353 }
2354
2355
2356
2357
2358
2359
2360 var dwsectCUSizeMu sync.Mutex
2361 var dwsectCUSize map[string]uint64
2362
2363
2364 func getDwsectCUSize(sname string, pkgname string) uint64 {
2365 return dwsectCUSize[sname+"."+pkgname]
2366 }
2367
2368 func addDwsectCUSize(sname string, pkgname string, size uint64) {
2369 dwsectCUSizeMu.Lock()
2370 defer dwsectCUSizeMu.Unlock()
2371 dwsectCUSize[sname+"."+pkgname] += size
2372 }
2373
View as plain text