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