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