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