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 objabi.KindBool:
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 objabi.KindInt,
552 objabi.KindInt8,
553 objabi.KindInt16,
554 objabi.KindInt32,
555 objabi.KindInt64:
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 objabi.KindUint,
561 objabi.KindUint8,
562 objabi.KindUint16,
563 objabi.KindUint32,
564 objabi.KindUint64,
565 objabi.KindUintptr:
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 objabi.KindFloat32,
571 objabi.KindFloat64:
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 objabi.KindComplex64,
577 objabi.KindComplex128:
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 objabi.KindArray:
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 objabi.KindChan:
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 objabi.KindFunc:
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 objabi.KindInterface:
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 objabi.KindMap:
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 objabi.KindPtr:
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 objabi.KindSlice:
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 objabi.KindString:
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 objabi.KindStruct:
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 objabi.KindUnsafePointer:
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(objabi.KindPtr), 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
854 const (
855 MaxKeySize = abi.MapMaxKeyBytes
856 MaxValSize = abi.MapMaxElemBytes
857 BucketSize = abi.MapBucketCount
858 )
859
860 func (d *dwctxt) mkinternaltype(ctxt *Link, abbrev int, typename, keyname, valname string, f func(*dwarf.DWDie)) loader.Sym {
861 name := mkinternaltypename(typename, keyname, valname)
862 symname := dwarf.InfoPrefix + name
863 s := d.ldr.Lookup(symname, 0)
864 if s != 0 && d.ldr.SymType(s) == sym.SDWARFTYPE {
865 return s
866 }
867 die := d.newdie(&dwtypes, abbrev, name)
868 f(die)
869 return d.dtolsym(die.Sym)
870 }
871
872 func (d *dwctxt) synthesizemaptypes(ctxt *Link, die *dwarf.DWDie) {
873 hash := walktypedef(d.findprotodie(ctxt, "type:runtime.hmap"))
874 bucket := walktypedef(d.findprotodie(ctxt, "type:runtime.bmap"))
875
876 if hash == nil {
877 return
878 }
879
880 for ; die != nil; die = die.Link {
881 if die.Abbrev != dwarf.DW_ABRV_MAPTYPE {
882 continue
883 }
884 gotype := loader.Sym(getattr(die, dwarf.DW_AT_type).Data.(dwSym))
885 keytype := decodetypeMapKey(d.ldr, d.arch, gotype)
886 valtype := decodetypeMapValue(d.ldr, d.arch, gotype)
887 keydata := d.ldr.Data(keytype)
888 valdata := d.ldr.Data(valtype)
889 keysize, valsize := decodetypeSize(d.arch, keydata), decodetypeSize(d.arch, valdata)
890 keytype, valtype = d.walksymtypedef(d.defgotype(keytype)), d.walksymtypedef(d.defgotype(valtype))
891
892
893 indirectKey, indirectVal := false, false
894 if keysize > MaxKeySize {
895 keysize = int64(d.arch.PtrSize)
896 indirectKey = true
897 }
898 if valsize > MaxValSize {
899 valsize = int64(d.arch.PtrSize)
900 indirectVal = true
901 }
902
903
904 keyname := d.nameFromDIESym(keytype)
905 dwhks := d.mkinternaltype(ctxt, dwarf.DW_ABRV_ARRAYTYPE, "[]key", keyname, "", func(dwhk *dwarf.DWDie) {
906 newattr(dwhk, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, BucketSize*keysize, 0)
907 t := keytype
908 if indirectKey {
909 t = d.defptrto(keytype)
910 }
911 d.newrefattr(dwhk, dwarf.DW_AT_type, t)
912 fld := d.newdie(dwhk, dwarf.DW_ABRV_ARRAYRANGE, "size")
913 newattr(fld, dwarf.DW_AT_count, dwarf.DW_CLS_CONSTANT, BucketSize, 0)
914 d.newrefattr(fld, dwarf.DW_AT_type, d.uintptrInfoSym)
915 })
916
917
918 valname := d.nameFromDIESym(valtype)
919 dwhvs := d.mkinternaltype(ctxt, dwarf.DW_ABRV_ARRAYTYPE, "[]val", valname, "", func(dwhv *dwarf.DWDie) {
920 newattr(dwhv, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, BucketSize*valsize, 0)
921 t := valtype
922 if indirectVal {
923 t = d.defptrto(valtype)
924 }
925 d.newrefattr(dwhv, dwarf.DW_AT_type, t)
926 fld := d.newdie(dwhv, dwarf.DW_ABRV_ARRAYRANGE, "size")
927 newattr(fld, dwarf.DW_AT_count, dwarf.DW_CLS_CONSTANT, BucketSize, 0)
928 d.newrefattr(fld, dwarf.DW_AT_type, d.uintptrInfoSym)
929 })
930
931
932 dwhbs := d.mkinternaltype(ctxt, dwarf.DW_ABRV_STRUCTTYPE, "bucket", keyname, valname, func(dwhb *dwarf.DWDie) {
933
934
935 d.copychildrenexcept(ctxt, dwhb, bucket, findchild(bucket, "data"))
936
937 fld := d.newdie(dwhb, dwarf.DW_ABRV_STRUCTFIELD, "keys")
938 d.newrefattr(fld, dwarf.DW_AT_type, dwhks)
939 newmemberoffsetattr(fld, BucketSize)
940 fld = d.newdie(dwhb, dwarf.DW_ABRV_STRUCTFIELD, "values")
941 d.newrefattr(fld, dwarf.DW_AT_type, dwhvs)
942 newmemberoffsetattr(fld, BucketSize+BucketSize*int32(keysize))
943 fld = d.newdie(dwhb, dwarf.DW_ABRV_STRUCTFIELD, "overflow")
944 d.newrefattr(fld, dwarf.DW_AT_type, d.defptrto(d.dtolsym(dwhb.Sym)))
945 newmemberoffsetattr(fld, BucketSize+BucketSize*(int32(keysize)+int32(valsize)))
946 if d.arch.RegSize > d.arch.PtrSize {
947 fld = d.newdie(dwhb, dwarf.DW_ABRV_STRUCTFIELD, "pad")
948 d.newrefattr(fld, dwarf.DW_AT_type, d.uintptrInfoSym)
949 newmemberoffsetattr(fld, BucketSize+BucketSize*(int32(keysize)+int32(valsize))+int32(d.arch.PtrSize))
950 }
951
952 newattr(dwhb, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, BucketSize+BucketSize*keysize+BucketSize*valsize+int64(d.arch.RegSize), 0)
953 })
954
955
956 dwhs := d.mkinternaltype(ctxt, dwarf.DW_ABRV_STRUCTTYPE, "hash", keyname, valname, func(dwh *dwarf.DWDie) {
957 d.copychildren(ctxt, dwh, hash)
958 d.substitutetype(dwh, "buckets", d.defptrto(dwhbs))
959 d.substitutetype(dwh, "oldbuckets", d.defptrto(dwhbs))
960 newattr(dwh, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, getattr(hash, dwarf.DW_AT_byte_size).Value, nil)
961 })
962
963
964 d.newrefattr(die, dwarf.DW_AT_type, d.defptrto(dwhs))
965 }
966 }
967
968 func (d *dwctxt) synthesizechantypes(ctxt *Link, die *dwarf.DWDie) {
969 sudog := walktypedef(d.findprotodie(ctxt, "type:runtime.sudog"))
970 waitq := walktypedef(d.findprotodie(ctxt, "type:runtime.waitq"))
971 hchan := walktypedef(d.findprotodie(ctxt, "type:runtime.hchan"))
972 if sudog == nil || waitq == nil || hchan == nil {
973 return
974 }
975
976 sudogsize := int(getattr(sudog, dwarf.DW_AT_byte_size).Value)
977
978 for ; die != nil; die = die.Link {
979 if die.Abbrev != dwarf.DW_ABRV_CHANTYPE {
980 continue
981 }
982 elemgotype := loader.Sym(getattr(die, dwarf.DW_AT_type).Data.(dwSym))
983 tname := d.ldr.SymName(elemgotype)
984 elemname := tname[5:]
985 elemtype := d.walksymtypedef(d.defgotype(d.lookupOrDiag(tname)))
986
987
988 dwss := d.mkinternaltype(ctxt, dwarf.DW_ABRV_STRUCTTYPE, "sudog", elemname, "", func(dws *dwarf.DWDie) {
989 d.copychildren(ctxt, dws, sudog)
990 d.substitutetype(dws, "elem", d.defptrto(elemtype))
991 newattr(dws, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, int64(sudogsize), nil)
992 })
993
994
995 dwws := d.mkinternaltype(ctxt, dwarf.DW_ABRV_STRUCTTYPE, "waitq", elemname, "", func(dww *dwarf.DWDie) {
996
997 d.copychildren(ctxt, dww, waitq)
998 d.substitutetype(dww, "first", d.defptrto(dwss))
999 d.substitutetype(dww, "last", d.defptrto(dwss))
1000 newattr(dww, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, getattr(waitq, dwarf.DW_AT_byte_size).Value, nil)
1001 })
1002
1003
1004 dwhs := d.mkinternaltype(ctxt, dwarf.DW_ABRV_STRUCTTYPE, "hchan", elemname, "", func(dwh *dwarf.DWDie) {
1005 d.copychildren(ctxt, dwh, hchan)
1006 d.substitutetype(dwh, "recvq", dwws)
1007 d.substitutetype(dwh, "sendq", dwws)
1008 newattr(dwh, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, getattr(hchan, dwarf.DW_AT_byte_size).Value, nil)
1009 })
1010
1011 d.newrefattr(die, dwarf.DW_AT_type, d.defptrto(dwhs))
1012 }
1013 }
1014
1015
1016
1017 func (d *dwctxt) createUnitLength(su *loader.SymbolBuilder, v uint64) {
1018 if isDwarf64(d.linkctxt) {
1019 su.AddUint32(d.arch, 0xFFFFFFFF)
1020 }
1021 d.addDwarfAddrField(su, v)
1022 }
1023
1024
1025 func (d *dwctxt) addDwarfAddrField(sb *loader.SymbolBuilder, v uint64) {
1026 if isDwarf64(d.linkctxt) {
1027 sb.AddUint(d.arch, v)
1028 } else {
1029 sb.AddUint32(d.arch, uint32(v))
1030 }
1031 }
1032
1033
1034 func (d *dwctxt) addDwarfAddrRef(sb *loader.SymbolBuilder, t loader.Sym) {
1035 if isDwarf64(d.linkctxt) {
1036 d.adddwarfref(sb, t, 8)
1037 } else {
1038 d.adddwarfref(sb, t, 4)
1039 }
1040 }
1041
1042
1043 func (d *dwctxt) calcCompUnitRanges() {
1044 var prevUnit *sym.CompilationUnit
1045 for _, s := range d.linkctxt.Textp {
1046 sym := loader.Sym(s)
1047
1048 fi := d.ldr.FuncInfo(sym)
1049 if !fi.Valid() {
1050 continue
1051 }
1052
1053
1054
1055 unit := d.ldr.SymUnit(sym)
1056 if unit == nil {
1057 continue
1058 }
1059
1060
1061
1062
1063
1064
1065
1066
1067 sval := d.ldr.SymValue(sym)
1068 u0val := d.ldr.SymValue(loader.Sym(unit.Textp[0]))
1069 if prevUnit != unit {
1070 unit.PCs = append(unit.PCs, dwarf.Range{Start: sval - u0val})
1071 prevUnit = unit
1072 }
1073 unit.PCs[len(unit.PCs)-1].End = sval - u0val + int64(len(d.ldr.Data(sym)))
1074 }
1075 }
1076
1077 func movetomodule(ctxt *Link, parent *dwarf.DWDie) {
1078 die := ctxt.runtimeCU.DWInfo.Child
1079 if die == nil {
1080 ctxt.runtimeCU.DWInfo.Child = parent.Child
1081 return
1082 }
1083 for die.Link != nil {
1084 die = die.Link
1085 }
1086 die.Link = parent.Child
1087 }
1088
1089
1093 const (
1094 LINE_BASE = -4
1095 LINE_RANGE = 10
1096 PC_RANGE = (255 - OPCODE_BASE) / LINE_RANGE
1097 OPCODE_BASE = 11
1098 )
1099
1100
1103
1104 func getCompilationDir() string {
1105
1106
1107
1108
1109
1110
1111 return "."
1112 }
1113
1114 func (d *dwctxt) importInfoSymbol(dsym loader.Sym) {
1115 d.ldr.SetAttrReachable(dsym, true)
1116 d.ldr.SetAttrNotInSymbolTable(dsym, true)
1117 dst := d.ldr.SymType(dsym)
1118 if dst != sym.SDWARFCONST && dst != sym.SDWARFABSFCN {
1119 log.Fatalf("error: DWARF info sym %d/%s with incorrect type %s", dsym, d.ldr.SymName(dsym), d.ldr.SymType(dsym).String())
1120 }
1121 relocs := d.ldr.Relocs(dsym)
1122 for i := 0; i < relocs.Count(); i++ {
1123 r := relocs.At(i)
1124 if r.Type() != objabi.R_DWARFSECREF {
1125 continue
1126 }
1127 rsym := r.Sym()
1128
1129
1130 if _, ok := d.rtmap[rsym]; ok {
1131
1132 continue
1133 }
1134
1135
1136 sn := d.ldr.SymName(rsym)
1137 tn := sn[len(dwarf.InfoPrefix):]
1138 ts := d.ldr.Lookup("type:"+tn, 0)
1139 d.defgotype(ts)
1140 }
1141 }
1142
1143 func expandFile(fname string) string {
1144 fname = strings.TrimPrefix(fname, src.FileSymPrefix)
1145 return expandGoroot(fname)
1146 }
1147
1148
1149
1150
1151
1152
1153
1154 func (d *dwctxt) writeDirFileTables(unit *sym.CompilationUnit, lsu *loader.SymbolBuilder) {
1155 type fileDir struct {
1156 base string
1157 dir int
1158 }
1159 dirNums := make(map[string]int)
1160 dirs := []string{""}
1161 files := []fileDir{}
1162
1163
1164
1165 for i, name := range unit.FileTable {
1166 name := expandFile(name)
1167 if len(name) == 0 {
1168
1169
1170 name = fmt.Sprintf("<missing>_%d", i)
1171 }
1172
1173
1174
1175 file := path.Base(name)
1176 dir := path.Dir(name)
1177 dirIdx, ok := dirNums[dir]
1178 if !ok && dir != "." {
1179 dirIdx = len(dirNums) + 1
1180 dirNums[dir] = dirIdx
1181 dirs = append(dirs, dir)
1182 }
1183 files = append(files, fileDir{base: file, dir: dirIdx})
1184
1185
1186
1187
1188 if i := strings.Index(name, "runtime/proc.go"); i >= 0 && unit.Lib.Pkg == "runtime" {
1189 d.dwmu.Lock()
1190 if gdbscript == "" {
1191 k := strings.Index(name, "runtime/proc.go")
1192 gdbscript = name[:k] + "runtime/runtime-gdb.py"
1193 }
1194 d.dwmu.Unlock()
1195 }
1196 }
1197
1198
1199
1200 lsDwsym := dwSym(lsu.Sym())
1201 for k := 1; k < len(dirs); k++ {
1202 d.AddString(lsDwsym, dirs[k])
1203 }
1204 lsu.AddUint8(0)
1205
1206
1207 for k := 0; k < len(files); k++ {
1208 d.AddString(lsDwsym, files[k].base)
1209 dwarf.Uleb128put(d, lsDwsym, int64(files[k].dir))
1210 lsu.AddUint8(0)
1211 lsu.AddUint8(0)
1212 }
1213 lsu.AddUint8(0)
1214 }
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224 func (d *dwctxt) writelines(unit *sym.CompilationUnit, lineProlog loader.Sym) []loader.Sym {
1225 is_stmt := uint8(1)
1226
1227 unitstart := int64(-1)
1228 headerstart := int64(-1)
1229 headerend := int64(-1)
1230
1231 syms := make([]loader.Sym, 0, len(unit.Textp)+2)
1232 syms = append(syms, lineProlog)
1233 lsu := d.ldr.MakeSymbolUpdater(lineProlog)
1234 lsDwsym := dwSym(lineProlog)
1235 newattr(unit.DWInfo, dwarf.DW_AT_stmt_list, dwarf.DW_CLS_PTR, 0, lsDwsym)
1236
1237
1238
1239 unitLengthOffset := lsu.Size()
1240 d.createUnitLength(lsu, 0)
1241 unitstart = lsu.Size()
1242 lsu.AddUint16(d.arch, 2)
1243 headerLengthOffset := lsu.Size()
1244 d.addDwarfAddrField(lsu, 0)
1245 headerstart = lsu.Size()
1246
1247
1248 lsu.AddUint8(1)
1249 lsu.AddUint8(is_stmt)
1250 lsu.AddUint8(LINE_BASE & 0xFF)
1251 lsu.AddUint8(LINE_RANGE)
1252 lsu.AddUint8(OPCODE_BASE)
1253 lsu.AddUint8(0)
1254 lsu.AddUint8(1)
1255 lsu.AddUint8(1)
1256 lsu.AddUint8(1)
1257 lsu.AddUint8(1)
1258 lsu.AddUint8(0)
1259 lsu.AddUint8(0)
1260 lsu.AddUint8(0)
1261 lsu.AddUint8(1)
1262 lsu.AddUint8(0)
1263
1264
1265 d.writeDirFileTables(unit, lsu)
1266
1267
1268 headerend = lsu.Size()
1269 unitlen := lsu.Size() - unitstart
1270
1271
1272 for _, s := range unit.Textp {
1273 fnSym := loader.Sym(s)
1274 _, _, _, lines := d.ldr.GetFuncDwarfAuxSyms(fnSym)
1275
1276
1277 if lines != 0 {
1278 syms = append(syms, lines)
1279 unitlen += int64(len(d.ldr.Data(lines)))
1280 }
1281 }
1282
1283 if d.linkctxt.HeadType == objabi.Haix {
1284 addDwsectCUSize(".debug_line", unit.Lib.Pkg, uint64(unitlen))
1285 }
1286
1287 if isDwarf64(d.linkctxt) {
1288 lsu.SetUint(d.arch, unitLengthOffset+4, uint64(unitlen))
1289 lsu.SetUint(d.arch, headerLengthOffset, uint64(headerend-headerstart))
1290 } else {
1291 lsu.SetUint32(d.arch, unitLengthOffset, uint32(unitlen))
1292 lsu.SetUint32(d.arch, headerLengthOffset, uint32(headerend-headerstart))
1293 }
1294
1295 return syms
1296 }
1297
1298
1299
1300
1301 func (d *dwctxt) writepcranges(unit *sym.CompilationUnit, base loader.Sym, pcs []dwarf.Range, rangeProlog loader.Sym) []loader.Sym {
1302
1303 syms := make([]loader.Sym, 0, len(unit.RangeSyms)+1)
1304 syms = append(syms, rangeProlog)
1305 rsu := d.ldr.MakeSymbolUpdater(rangeProlog)
1306 rDwSym := dwSym(rangeProlog)
1307
1308
1309 newattr(unit.DWInfo, dwarf.DW_AT_ranges, dwarf.DW_CLS_PTR, rsu.Size(), rDwSym)
1310 newattr(unit.DWInfo, dwarf.DW_AT_low_pc, dwarf.DW_CLS_ADDRESS, 0, dwSym(base))
1311 dwarf.PutBasedRanges(d, rDwSym, pcs)
1312
1313
1314 rsize := uint64(rsu.Size())
1315 for _, ls := range unit.RangeSyms {
1316 s := loader.Sym(ls)
1317 syms = append(syms, s)
1318 rsize += uint64(d.ldr.SymSize(s))
1319 }
1320
1321 if d.linkctxt.HeadType == objabi.Haix {
1322 addDwsectCUSize(".debug_ranges", unit.Lib.Pkg, rsize)
1323 }
1324
1325 return syms
1326 }
1327
1328
1331 const (
1332 dataAlignmentFactor = -4
1333 )
1334
1335
1336 func appendPCDeltaCFA(arch *sys.Arch, b []byte, deltapc, cfa int64) []byte {
1337 b = append(b, dwarf.DW_CFA_def_cfa_offset_sf)
1338 b = dwarf.AppendSleb128(b, cfa/dataAlignmentFactor)
1339
1340 switch {
1341 case deltapc < 0x40:
1342 b = append(b, uint8(dwarf.DW_CFA_advance_loc+deltapc))
1343 case deltapc < 0x100:
1344 b = append(b, dwarf.DW_CFA_advance_loc1)
1345 b = append(b, uint8(deltapc))
1346 case deltapc < 0x10000:
1347 b = append(b, dwarf.DW_CFA_advance_loc2, 0, 0)
1348 arch.ByteOrder.PutUint16(b[len(b)-2:], uint16(deltapc))
1349 default:
1350 b = append(b, dwarf.DW_CFA_advance_loc4, 0, 0, 0, 0)
1351 arch.ByteOrder.PutUint32(b[len(b)-4:], uint32(deltapc))
1352 }
1353 return b
1354 }
1355
1356 func (d *dwctxt) writeframes(fs loader.Sym) dwarfSecInfo {
1357 fsd := dwSym(fs)
1358 fsu := d.ldr.MakeSymbolUpdater(fs)
1359 fsu.SetType(sym.SDWARFSECT)
1360 isdw64 := isDwarf64(d.linkctxt)
1361 haslr := d.linkctxt.Arch.HasLR
1362
1363
1364 lengthFieldSize := int64(4)
1365 if isdw64 {
1366 lengthFieldSize += 8
1367 }
1368
1369
1370 cieReserve := uint32(16)
1371 if haslr {
1372 cieReserve = 32
1373 }
1374 if isdw64 {
1375 cieReserve += 4
1376 }
1377 d.createUnitLength(fsu, uint64(cieReserve))
1378 d.addDwarfAddrField(fsu, ^uint64(0))
1379 fsu.AddUint8(3)
1380 fsu.AddUint8(0)
1381 dwarf.Uleb128put(d, fsd, 1)
1382 dwarf.Sleb128put(d, fsd, dataAlignmentFactor)
1383 dwarf.Uleb128put(d, fsd, int64(thearch.Dwarfreglr))
1384
1385 fsu.AddUint8(dwarf.DW_CFA_def_cfa)
1386 dwarf.Uleb128put(d, fsd, int64(thearch.Dwarfregsp))
1387 if haslr {
1388 dwarf.Uleb128put(d, fsd, int64(0))
1389
1390 fsu.AddUint8(dwarf.DW_CFA_same_value)
1391 dwarf.Uleb128put(d, fsd, int64(thearch.Dwarfreglr))
1392
1393 fsu.AddUint8(dwarf.DW_CFA_val_offset)
1394 dwarf.Uleb128put(d, fsd, int64(thearch.Dwarfregsp))
1395 dwarf.Uleb128put(d, fsd, int64(0))
1396 } else {
1397 dwarf.Uleb128put(d, fsd, int64(d.arch.PtrSize))
1398
1399 fsu.AddUint8(dwarf.DW_CFA_offset_extended)
1400 dwarf.Uleb128put(d, fsd, int64(thearch.Dwarfreglr))
1401 dwarf.Uleb128put(d, fsd, int64(-d.arch.PtrSize)/dataAlignmentFactor)
1402 }
1403
1404 pad := int64(cieReserve) + lengthFieldSize - int64(len(d.ldr.Data(fs)))
1405
1406 if pad < 0 {
1407 Exitf("dwarf: cieReserve too small by %d bytes.", -pad)
1408 }
1409
1410 internalExec := d.linkctxt.BuildMode == BuildModeExe && d.linkctxt.IsInternal()
1411 addAddrPlus := loader.GenAddAddrPlusFunc(internalExec)
1412
1413 fsu.AddBytes(zeros[:pad])
1414
1415 var deltaBuf []byte
1416 pcsp := obj.NewPCIter(uint32(d.arch.MinLC))
1417 for _, s := range d.linkctxt.Textp {
1418 fn := loader.Sym(s)
1419 fi := d.ldr.FuncInfo(fn)
1420 if !fi.Valid() {
1421 continue
1422 }
1423 fpcsp := d.ldr.Pcsp(s)
1424
1425
1426
1427 deltaBuf = deltaBuf[:0]
1428 if haslr && fi.TopFrame() {
1429
1430
1431
1432 deltaBuf = append(deltaBuf, dwarf.DW_CFA_undefined)
1433 deltaBuf = dwarf.AppendUleb128(deltaBuf, uint64(thearch.Dwarfreglr))
1434 }
1435
1436 for pcsp.Init(d.linkctxt.loader.Data(fpcsp)); !pcsp.Done; pcsp.Next() {
1437 nextpc := pcsp.NextPC
1438
1439
1440
1441 if int64(nextpc) == int64(len(d.ldr.Data(fn))) {
1442 nextpc--
1443 if nextpc < pcsp.PC {
1444 continue
1445 }
1446 }
1447
1448 spdelta := int64(pcsp.Value)
1449 if !haslr {
1450
1451 spdelta += int64(d.arch.PtrSize)
1452 }
1453
1454 if haslr && !fi.TopFrame() {
1455
1456
1457
1458 if pcsp.Value > 0 {
1459
1460
1461 deltaBuf = append(deltaBuf, dwarf.DW_CFA_offset_extended_sf)
1462 deltaBuf = dwarf.AppendUleb128(deltaBuf, uint64(thearch.Dwarfreglr))
1463 deltaBuf = dwarf.AppendSleb128(deltaBuf, -spdelta/dataAlignmentFactor)
1464 } else {
1465
1466
1467 deltaBuf = append(deltaBuf, dwarf.DW_CFA_same_value)
1468 deltaBuf = dwarf.AppendUleb128(deltaBuf, uint64(thearch.Dwarfreglr))
1469 }
1470 }
1471
1472 deltaBuf = appendPCDeltaCFA(d.arch, deltaBuf, int64(nextpc)-int64(pcsp.PC), spdelta)
1473 }
1474 pad := int(Rnd(int64(len(deltaBuf)), int64(d.arch.PtrSize))) - len(deltaBuf)
1475 deltaBuf = append(deltaBuf, zeros[:pad]...)
1476
1477
1478
1479
1480
1481
1482
1483 fdeLength := uint64(4 + 2*d.arch.PtrSize + len(deltaBuf))
1484 if isdw64 {
1485 fdeLength += 4
1486 }
1487 d.createUnitLength(fsu, fdeLength)
1488
1489 if d.linkctxt.LinkMode == LinkExternal {
1490 d.addDwarfAddrRef(fsu, fs)
1491 } else {
1492 d.addDwarfAddrField(fsu, 0)
1493 }
1494 addAddrPlus(fsu, d.arch, s, 0)
1495 fsu.AddUintXX(d.arch, uint64(len(d.ldr.Data(fn))), d.arch.PtrSize)
1496 fsu.AddBytes(deltaBuf)
1497
1498 if d.linkctxt.HeadType == objabi.Haix {
1499 addDwsectCUSize(".debug_frame", d.ldr.SymPkg(fn), fdeLength+uint64(lengthFieldSize))
1500 }
1501 }
1502
1503 return dwarfSecInfo{syms: []loader.Sym{fs}}
1504 }
1505
1506
1509
1510 const (
1511 COMPUNITHEADERSIZE = 4 + 2 + 4 + 1
1512 )
1513
1514 func (d *dwctxt) writeUnitInfo(u *sym.CompilationUnit, abbrevsym loader.Sym, infoEpilog loader.Sym) []loader.Sym {
1515 syms := []loader.Sym{}
1516 if len(u.Textp) == 0 && u.DWInfo.Child == nil && len(u.VarDIEs) == 0 {
1517 return syms
1518 }
1519
1520 compunit := u.DWInfo
1521 s := d.dtolsym(compunit.Sym)
1522 su := d.ldr.MakeSymbolUpdater(s)
1523
1524
1525
1526
1527 d.createUnitLength(su, 0)
1528 su.AddUint16(d.arch, 4)
1529
1530
1531 d.addDwarfAddrRef(su, abbrevsym)
1532
1533 su.AddUint8(uint8(d.arch.PtrSize))
1534
1535 ds := dwSym(s)
1536 dwarf.Uleb128put(d, ds, int64(compunit.Abbrev))
1537 dwarf.PutAttrs(d, ds, compunit.Abbrev, compunit.Attr)
1538
1539
1540 cu := make([]loader.Sym, 0, len(u.AbsFnDIEs)+len(u.FuncDIEs))
1541 cu = append(cu, s)
1542 cu = append(cu, u.AbsFnDIEs...)
1543 cu = append(cu, u.FuncDIEs...)
1544 if u.Consts != 0 {
1545 cu = append(cu, loader.Sym(u.Consts))
1546 }
1547 cu = append(cu, u.VarDIEs...)
1548 var cusize int64
1549 for _, child := range cu {
1550 cusize += int64(len(d.ldr.Data(child)))
1551 }
1552
1553 for die := compunit.Child; die != nil; die = die.Link {
1554 l := len(cu)
1555 lastSymSz := int64(len(d.ldr.Data(cu[l-1])))
1556 cu = d.putdie(cu, die)
1557 if lastSymSz != int64(len(d.ldr.Data(cu[l-1]))) {
1558
1559 cusize = cusize - lastSymSz + int64(len(d.ldr.Data(cu[l-1])))
1560 }
1561 for _, child := range cu[l:] {
1562 cusize += int64(len(d.ldr.Data(child)))
1563 }
1564 }
1565
1566 culu := d.ldr.MakeSymbolUpdater(infoEpilog)
1567 culu.AddUint8(0)
1568 cu = append(cu, infoEpilog)
1569 cusize++
1570
1571
1572 if d.linkctxt.HeadType == objabi.Haix {
1573 addDwsectCUSize(".debug_info", d.getPkgFromCUSym(s), uint64(cusize))
1574 }
1575 if isDwarf64(d.linkctxt) {
1576 cusize -= 12
1577 su.SetUint(d.arch, 4, uint64(cusize))
1578 } else {
1579 cusize -= 4
1580 su.SetUint32(d.arch, 0, uint32(cusize))
1581 }
1582 return append(syms, cu...)
1583 }
1584
1585 func (d *dwctxt) writegdbscript() dwarfSecInfo {
1586
1587 if d.linkctxt.HeadType == objabi.Haix {
1588 return dwarfSecInfo{}
1589 }
1590 if d.linkctxt.LinkMode == LinkExternal && d.linkctxt.HeadType == objabi.Hwindows && d.linkctxt.BuildMode == BuildModeCArchive {
1591
1592
1593
1594
1595
1596
1597 return dwarfSecInfo{}
1598 }
1599 if gdbscript == "" {
1600 return dwarfSecInfo{}
1601 }
1602
1603 gs := d.ldr.CreateSymForUpdate(".debug_gdb_scripts", 0)
1604 gs.SetType(sym.SDWARFSECT)
1605
1606 gs.AddUint8(GdbScriptPythonFileId)
1607 gs.Addstring(gdbscript)
1608 return dwarfSecInfo{syms: []loader.Sym{gs.Sym()}}
1609 }
1610
1611
1612
1613
1614 var prototypedies map[string]*dwarf.DWDie
1615
1616 func dwarfEnabled(ctxt *Link) bool {
1617 if *FlagW {
1618 return false
1619 }
1620 if ctxt.HeadType == objabi.Hplan9 || ctxt.HeadType == objabi.Hjs || ctxt.HeadType == objabi.Hwasip1 {
1621 return false
1622 }
1623
1624 if ctxt.LinkMode == LinkExternal {
1625 switch {
1626 case ctxt.IsELF:
1627 case ctxt.HeadType == objabi.Hdarwin:
1628 case ctxt.HeadType == objabi.Hwindows:
1629 case ctxt.HeadType == objabi.Haix:
1630 res, err := dwarf.IsDWARFEnabledOnAIXLd(ctxt.extld())
1631 if err != nil {
1632 Exitf("%v", err)
1633 }
1634 return res
1635 default:
1636 return false
1637 }
1638 }
1639
1640 return true
1641 }
1642
1643
1644
1645 func (d *dwctxt) mkBuiltinType(ctxt *Link, abrv int, tname string) *dwarf.DWDie {
1646
1647 die := d.newdie(&dwtypes, abrv, tname)
1648
1649
1650 gotype := d.lookupOrDiag("type:" + tname)
1651
1652
1653 ds := loader.Sym(die.Sym.(dwSym))
1654 d.rtmap[ds] = gotype
1655
1656
1657 d.tdmap[gotype] = ds
1658
1659 return die
1660 }
1661
1662
1663
1664
1665 func (d *dwctxt) dwarfVisitFunction(fnSym loader.Sym, unit *sym.CompilationUnit) {
1666
1667
1668
1669 infosym, _, rangesym, _ := d.ldr.GetFuncDwarfAuxSyms(fnSym)
1670 if infosym == 0 {
1671 return
1672 }
1673 d.ldr.SetAttrNotInSymbolTable(infosym, true)
1674 d.ldr.SetAttrReachable(infosym, true)
1675 unit.FuncDIEs = append(unit.FuncDIEs, sym.LoaderSym(infosym))
1676 if rangesym != 0 {
1677 d.ldr.SetAttrNotInSymbolTable(rangesym, true)
1678 d.ldr.SetAttrReachable(rangesym, true)
1679 unit.RangeSyms = append(unit.RangeSyms, sym.LoaderSym(rangesym))
1680 }
1681
1682
1683
1684
1685
1686 drelocs := d.ldr.Relocs(infosym)
1687 for ri := 0; ri < drelocs.Count(); ri++ {
1688 r := drelocs.At(ri)
1689
1690 if r.Type() == objabi.R_USETYPE {
1691 d.defgotype(r.Sym())
1692 continue
1693 }
1694 if r.Type() != objabi.R_DWARFSECREF {
1695 continue
1696 }
1697
1698 rsym := r.Sym()
1699 rst := d.ldr.SymType(rsym)
1700
1701
1702 if rst == sym.SDWARFABSFCN {
1703 if !d.ldr.AttrOnList(rsym) {
1704
1705 d.ldr.SetAttrOnList(rsym, true)
1706 unit.AbsFnDIEs = append(unit.AbsFnDIEs, sym.LoaderSym(rsym))
1707 d.importInfoSymbol(rsym)
1708 }
1709 continue
1710 }
1711
1712
1713 if rst != sym.SDWARFTYPE && rst != sym.Sxxx {
1714 continue
1715 }
1716 if _, ok := d.rtmap[rsym]; ok {
1717
1718 continue
1719 }
1720
1721 rsn := d.ldr.SymName(rsym)
1722 tn := rsn[len(dwarf.InfoPrefix):]
1723 ts := d.ldr.Lookup("type:"+tn, 0)
1724 d.defgotype(ts)
1725 }
1726 }
1727
1728
1729
1730
1731
1732
1733
1734
1735 func dwarfGenerateDebugInfo(ctxt *Link) {
1736 if !dwarfEnabled(ctxt) {
1737 return
1738 }
1739
1740 d := &dwctxt{
1741 linkctxt: ctxt,
1742 ldr: ctxt.loader,
1743 arch: ctxt.Arch,
1744 tmap: make(map[string]loader.Sym),
1745 tdmap: make(map[loader.Sym]loader.Sym),
1746 rtmap: make(map[loader.Sym]loader.Sym),
1747 }
1748 d.typeRuntimeEface = d.lookupOrDiag("type:runtime.eface")
1749 d.typeRuntimeIface = d.lookupOrDiag("type:runtime.iface")
1750
1751 if ctxt.HeadType == objabi.Haix {
1752
1753 dwsectCUSize = make(map[string]uint64)
1754 }
1755
1756
1757 newattr(&dwtypes, dwarf.DW_AT_name, dwarf.DW_CLS_STRING, int64(len("dwtypes")), "dwtypes")
1758
1759
1760 d.newdie(&dwtypes, dwarf.DW_ABRV_NULLTYPE, "<unspecified>")
1761
1762
1763
1764 d.mkBuiltinType(ctxt, dwarf.DW_ABRV_BARE_PTRTYPE, "unsafe.Pointer")
1765 die := d.mkBuiltinType(ctxt, dwarf.DW_ABRV_BASETYPE, "uintptr")
1766 newattr(die, dwarf.DW_AT_encoding, dwarf.DW_CLS_CONSTANT, dwarf.DW_ATE_unsigned, 0)
1767 newattr(die, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, int64(d.arch.PtrSize), 0)
1768 newattr(die, dwarf.DW_AT_go_kind, dwarf.DW_CLS_CONSTANT, objabi.KindUintptr, 0)
1769 newattr(die, dwarf.DW_AT_go_runtime_type, dwarf.DW_CLS_ADDRESS, 0, dwSym(d.lookupOrDiag("type:uintptr")))
1770
1771 d.uintptrInfoSym = d.mustFind("uintptr")
1772
1773
1774 prototypedies = map[string]*dwarf.DWDie{
1775 "type:runtime.stringStructDWARF": nil,
1776 "type:runtime.slice": nil,
1777 "type:runtime.hmap": nil,
1778 "type:runtime.bmap": nil,
1779 "type:runtime.sudog": nil,
1780 "type:runtime.waitq": nil,
1781 "type:runtime.hchan": nil,
1782 }
1783
1784
1785 for _, typ := range []string{
1786 "type:internal/abi.Type",
1787 "type:internal/abi.ArrayType",
1788 "type:internal/abi.ChanType",
1789 "type:internal/abi.FuncType",
1790 "type:internal/abi.MapType",
1791 "type:internal/abi.PtrType",
1792 "type:internal/abi.SliceType",
1793 "type:internal/abi.StructType",
1794 "type:internal/abi.InterfaceType",
1795 "type:runtime.itab",
1796 "type:internal/abi.Imethod"} {
1797 d.defgotype(d.lookupOrDiag(typ))
1798 }
1799
1800
1801 var dwroot dwarf.DWDie
1802 flagVariants := make(map[string]bool)
1803
1804 for _, lib := range ctxt.Library {
1805
1806 consts := d.ldr.Lookup(dwarf.ConstInfoPrefix+lib.Pkg, 0)
1807 for _, unit := range lib.Units {
1808
1809 if consts != 0 {
1810 unit.Consts = sym.LoaderSym(consts)
1811 d.importInfoSymbol(consts)
1812 consts = 0
1813 }
1814 ctxt.compUnits = append(ctxt.compUnits, unit)
1815
1816
1817 if unit.Lib.Pkg == "runtime" {
1818 ctxt.runtimeCU = unit
1819 }
1820
1821 cuabrv := dwarf.DW_ABRV_COMPUNIT
1822 if len(unit.Textp) == 0 {
1823 cuabrv = dwarf.DW_ABRV_COMPUNIT_TEXTLESS
1824 }
1825 unit.DWInfo = d.newdie(&dwroot, cuabrv, unit.Lib.Pkg)
1826 newattr(unit.DWInfo, dwarf.DW_AT_language, dwarf.DW_CLS_CONSTANT, int64(dwarf.DW_LANG_Go), 0)
1827
1828 compDir := getCompilationDir()
1829
1830
1831
1832 newattr(unit.DWInfo, dwarf.DW_AT_comp_dir, dwarf.DW_CLS_STRING, int64(len(compDir)), compDir)
1833
1834 var peData []byte
1835 if producerExtra := d.ldr.Lookup(dwarf.CUInfoPrefix+"producer."+unit.Lib.Pkg, 0); producerExtra != 0 {
1836 peData = d.ldr.Data(producerExtra)
1837 }
1838 producer := "Go cmd/compile " + buildcfg.Version
1839 if len(peData) > 0 {
1840
1841
1842
1843
1844
1845
1846 producer += "; " + string(peData)
1847 flagVariants[string(peData)] = true
1848 } else {
1849 flagVariants[""] = true
1850 }
1851
1852 newattr(unit.DWInfo, dwarf.DW_AT_producer, dwarf.DW_CLS_STRING, int64(len(producer)), producer)
1853
1854 var pkgname string
1855 if pnSymIdx := d.ldr.Lookup(dwarf.CUInfoPrefix+"packagename."+unit.Lib.Pkg, 0); pnSymIdx != 0 {
1856 pnsData := d.ldr.Data(pnSymIdx)
1857 pkgname = string(pnsData)
1858 }
1859 newattr(unit.DWInfo, dwarf.DW_AT_go_package_name, dwarf.DW_CLS_STRING, int64(len(pkgname)), pkgname)
1860
1861
1862
1863
1864
1865 for _, s := range unit.Textp {
1866 d.dwarfVisitFunction(loader.Sym(s), unit)
1867 }
1868 }
1869 }
1870
1871
1872
1873
1874 if checkStrictDups > 1 && len(flagVariants) > 1 {
1875 checkStrictDups = 1
1876 }
1877
1878
1879
1880
1881
1882
1883
1884
1885 for idx := loader.Sym(1); idx < loader.Sym(d.ldr.NDef()); idx++ {
1886 if !d.ldr.AttrReachable(idx) ||
1887 d.ldr.AttrNotInSymbolTable(idx) ||
1888 d.ldr.SymVersion(idx) >= sym.SymVerStatic {
1889 continue
1890 }
1891 t := d.ldr.SymType(idx)
1892 switch t {
1893 case sym.SRODATA, sym.SDATA, sym.SNOPTRDATA, sym.STYPE, sym.SBSS, sym.SNOPTRBSS, sym.STLSBSS:
1894
1895 default:
1896 continue
1897 }
1898
1899 gt := d.ldr.SymGoType(idx)
1900 if gt == 0 {
1901 if t == sym.SRODATA {
1902 if d.ldr.IsDict(idx) {
1903
1904 relocs := d.ldr.Relocs(idx)
1905 for i := 0; i < relocs.Count(); i++ {
1906 reloc := relocs.At(i)
1907 if reloc.Type() == objabi.R_USEIFACE {
1908 d.defgotype(reloc.Sym())
1909 }
1910 }
1911 }
1912 }
1913 continue
1914 }
1915
1916
1917 if d.ldr.IsFileLocal(idx) {
1918 continue
1919 }
1920
1921
1922
1923
1924
1925
1926 varDIE := d.ldr.GetVarDwarfAuxSym(idx)
1927 if varDIE != 0 {
1928 unit := d.ldr.SymUnit(idx)
1929 d.defgotype(gt)
1930 unit.VarDIEs = append(unit.VarDIEs, sym.LoaderSym(varDIE))
1931 }
1932 }
1933
1934 d.synthesizestringtypes(ctxt, dwtypes.Child)
1935 d.synthesizeslicetypes(ctxt, dwtypes.Child)
1936 d.synthesizemaptypes(ctxt, dwtypes.Child)
1937 d.synthesizechantypes(ctxt, dwtypes.Child)
1938 }
1939
1940
1941
1942
1943 func dwarfGenerateDebugSyms(ctxt *Link) {
1944 if !dwarfEnabled(ctxt) {
1945 return
1946 }
1947 d := &dwctxt{
1948 linkctxt: ctxt,
1949 ldr: ctxt.loader,
1950 arch: ctxt.Arch,
1951 dwmu: new(sync.Mutex),
1952 }
1953 d.dwarfGenerateDebugSyms()
1954 }
1955
1956
1957
1958 type dwUnitSyms struct {
1959
1960 lineProlog loader.Sym
1961 rangeProlog loader.Sym
1962 infoEpilog loader.Sym
1963
1964
1965 linesyms []loader.Sym
1966 infosyms []loader.Sym
1967 locsyms []loader.Sym
1968 rangessyms []loader.Sym
1969 }
1970
1971
1972
1973
1974
1975
1976 func (d *dwctxt) dwUnitPortion(u *sym.CompilationUnit, abbrevsym loader.Sym, us *dwUnitSyms) {
1977 if u.DWInfo.Abbrev != dwarf.DW_ABRV_COMPUNIT_TEXTLESS {
1978 us.linesyms = d.writelines(u, us.lineProlog)
1979 base := loader.Sym(u.Textp[0])
1980 us.rangessyms = d.writepcranges(u, base, u.PCs, us.rangeProlog)
1981 us.locsyms = d.collectUnitLocs(u)
1982 }
1983 us.infosyms = d.writeUnitInfo(u, abbrevsym, us.infoEpilog)
1984 }
1985
1986 func (d *dwctxt) dwarfGenerateDebugSyms() {
1987 abbrevSec := d.writeabbrev()
1988 dwarfp = append(dwarfp, abbrevSec)
1989 d.calcCompUnitRanges()
1990 sort.Sort(compilationUnitByStartPC(d.linkctxt.compUnits))
1991
1992
1993
1994
1995 for _, u := range d.linkctxt.compUnits {
1996 reversetree(&u.DWInfo.Child)
1997 }
1998 reversetree(&dwtypes.Child)
1999 movetomodule(d.linkctxt, &dwtypes)
2000
2001 mkSecSym := func(name string) loader.Sym {
2002 s := d.ldr.CreateSymForUpdate(name, 0)
2003 s.SetType(sym.SDWARFSECT)
2004 s.SetReachable(true)
2005 return s.Sym()
2006 }
2007 mkAnonSym := func(kind sym.SymKind) loader.Sym {
2008 s := d.ldr.MakeSymbolUpdater(d.ldr.CreateExtSym("", 0))
2009 s.SetType(kind)
2010 s.SetReachable(true)
2011 return s.Sym()
2012 }
2013
2014
2015 frameSym := mkSecSym(".debug_frame")
2016 locSym := mkSecSym(".debug_loc")
2017 lineSym := mkSecSym(".debug_line")
2018 rangesSym := mkSecSym(".debug_ranges")
2019 infoSym := mkSecSym(".debug_info")
2020
2021
2022 lineSec := dwarfSecInfo{syms: []loader.Sym{lineSym}}
2023 locSec := dwarfSecInfo{syms: []loader.Sym{locSym}}
2024 rangesSec := dwarfSecInfo{syms: []loader.Sym{rangesSym}}
2025 frameSec := dwarfSecInfo{syms: []loader.Sym{frameSym}}
2026 infoSec := dwarfSecInfo{syms: []loader.Sym{infoSym}}
2027
2028
2029
2030 ncu := len(d.linkctxt.compUnits)
2031 unitSyms := make([]dwUnitSyms, ncu)
2032 for i := 0; i < ncu; i++ {
2033 us := &unitSyms[i]
2034 us.lineProlog = mkAnonSym(sym.SDWARFLINES)
2035 us.rangeProlog = mkAnonSym(sym.SDWARFRANGE)
2036 us.infoEpilog = mkAnonSym(sym.SDWARFFCN)
2037 }
2038
2039 var wg sync.WaitGroup
2040 sema := make(chan struct{}, runtime.GOMAXPROCS(0))
2041
2042
2043
2044 wg.Add(1)
2045 go func() {
2046 sema <- struct{}{}
2047 defer func() {
2048 <-sema
2049 wg.Done()
2050 }()
2051 frameSec = d.writeframes(frameSym)
2052 }()
2053
2054
2055
2056
2057 wg.Add(len(d.linkctxt.compUnits))
2058 for i := 0; i < ncu; i++ {
2059 go func(u *sym.CompilationUnit, us *dwUnitSyms) {
2060 sema <- struct{}{}
2061 defer func() {
2062 <-sema
2063 wg.Done()
2064 }()
2065 d.dwUnitPortion(u, abbrevSec.secSym(), us)
2066 }(d.linkctxt.compUnits[i], &unitSyms[i])
2067 }
2068 wg.Wait()
2069
2070 markReachable := func(syms []loader.Sym) []loader.Sym {
2071 for _, s := range syms {
2072 d.ldr.SetAttrNotInSymbolTable(s, true)
2073 d.ldr.SetAttrReachable(s, true)
2074 }
2075 return syms
2076 }
2077
2078
2079 for i := 0; i < ncu; i++ {
2080 r := &unitSyms[i]
2081 lineSec.syms = append(lineSec.syms, markReachable(r.linesyms)...)
2082 infoSec.syms = append(infoSec.syms, markReachable(r.infosyms)...)
2083 locSec.syms = append(locSec.syms, markReachable(r.locsyms)...)
2084 rangesSec.syms = append(rangesSec.syms, markReachable(r.rangessyms)...)
2085 }
2086 dwarfp = append(dwarfp, lineSec)
2087 dwarfp = append(dwarfp, frameSec)
2088 gdbScriptSec := d.writegdbscript()
2089 if gdbScriptSec.secSym() != 0 {
2090 dwarfp = append(dwarfp, gdbScriptSec)
2091 }
2092 dwarfp = append(dwarfp, infoSec)
2093 if len(locSec.syms) > 1 {
2094 dwarfp = append(dwarfp, locSec)
2095 }
2096 dwarfp = append(dwarfp, rangesSec)
2097
2098
2099
2100
2101
2102 seen := loader.MakeBitmap(d.ldr.NSym())
2103 for _, s := range infoSec.syms {
2104 if seen.Has(s) {
2105 log.Fatalf("symbol %s listed multiple times", d.ldr.SymName(s))
2106 }
2107 seen.Set(s)
2108 }
2109 }
2110
2111 func (d *dwctxt) collectUnitLocs(u *sym.CompilationUnit) []loader.Sym {
2112 syms := []loader.Sym{}
2113 for _, fn := range u.FuncDIEs {
2114 relocs := d.ldr.Relocs(loader.Sym(fn))
2115 for i := 0; i < relocs.Count(); i++ {
2116 reloc := relocs.At(i)
2117 if reloc.Type() != objabi.R_DWARFSECREF {
2118 continue
2119 }
2120 rsym := reloc.Sym()
2121 if d.ldr.SymType(rsym) == sym.SDWARFLOC {
2122 syms = append(syms, rsym)
2123
2124 break
2125 }
2126 }
2127 }
2128 return syms
2129 }
2130
2131
2132
2133 func dwarfaddshstrings(ctxt *Link, add func(string)) {
2134 if *FlagW {
2135 return
2136 }
2137
2138 secs := []string{"abbrev", "frame", "info", "loc", "line", "gdb_scripts", "ranges"}
2139 for _, sec := range secs {
2140 add(".debug_" + sec)
2141 if ctxt.IsExternal() {
2142 add(elfRelType + ".debug_" + sec)
2143 }
2144 }
2145 }
2146
2147 func dwarfaddelfsectionsyms(ctxt *Link) {
2148 if *FlagW {
2149 return
2150 }
2151 if ctxt.LinkMode != LinkExternal {
2152 return
2153 }
2154
2155 ldr := ctxt.loader
2156 for _, si := range dwarfp {
2157 s := si.secSym()
2158 sect := ldr.SymSect(si.secSym())
2159 putelfsectionsym(ctxt, ctxt.Out, s, sect.Elfsect.(*ElfShdr).shnum)
2160 }
2161 }
2162
2163
2164
2165
2166 func dwarfcompress(ctxt *Link) {
2167
2168 type compressedSect struct {
2169 index int
2170 compressed []byte
2171 syms []loader.Sym
2172 }
2173
2174 supported := ctxt.IsELF || ctxt.IsWindows() || ctxt.IsDarwin()
2175 if !ctxt.compressDWARF || !supported || ctxt.IsExternal() {
2176 return
2177 }
2178
2179 var compressedCount int
2180 resChannel := make(chan compressedSect)
2181 for i := range dwarfp {
2182 go func(resIndex int, syms []loader.Sym) {
2183 resChannel <- compressedSect{resIndex, compressSyms(ctxt, syms), syms}
2184 }(compressedCount, dwarfp[i].syms)
2185 compressedCount++
2186 }
2187 res := make([]compressedSect, compressedCount)
2188 for ; compressedCount > 0; compressedCount-- {
2189 r := <-resChannel
2190 res[r.index] = r
2191 }
2192
2193 ldr := ctxt.loader
2194 var newDwarfp []dwarfSecInfo
2195 Segdwarf.Sections = Segdwarf.Sections[:0]
2196 for _, z := range res {
2197 s := z.syms[0]
2198 if z.compressed == nil {
2199
2200 ds := dwarfSecInfo{syms: z.syms}
2201 newDwarfp = append(newDwarfp, ds)
2202 Segdwarf.Sections = append(Segdwarf.Sections, ldr.SymSect(s))
2203 } else {
2204 var compressedSegName string
2205 if ctxt.IsELF {
2206 compressedSegName = ldr.SymSect(s).Name
2207 } else {
2208 compressedSegName = ".zdebug_" + ldr.SymSect(s).Name[len(".debug_"):]
2209 }
2210 sect := addsection(ctxt.loader, ctxt.Arch, &Segdwarf, compressedSegName, 04)
2211 sect.Align = int32(ctxt.Arch.Alignment)
2212 sect.Length = uint64(len(z.compressed))
2213 sect.Compressed = true
2214 newSym := ldr.MakeSymbolBuilder(compressedSegName)
2215 ldr.SetAttrReachable(s, true)
2216 newSym.SetData(z.compressed)
2217 newSym.SetSize(int64(len(z.compressed)))
2218 ldr.SetSymSect(newSym.Sym(), sect)
2219 ds := dwarfSecInfo{syms: []loader.Sym{newSym.Sym()}}
2220 newDwarfp = append(newDwarfp, ds)
2221
2222
2223 for _, s := range z.syms {
2224 ldr.SetAttrReachable(s, false)
2225 ldr.FreeSym(s)
2226 }
2227 }
2228 }
2229 dwarfp = newDwarfp
2230
2231
2232
2233
2234 pos := Segdwarf.Vaddr
2235 var prevSect *sym.Section
2236 for _, si := range dwarfp {
2237 for _, s := range si.syms {
2238 ldr.SetSymValue(s, int64(pos))
2239 sect := ldr.SymSect(s)
2240 if sect != prevSect {
2241 sect.Vaddr = uint64(pos)
2242 prevSect = sect
2243 }
2244 if ldr.SubSym(s) != 0 {
2245 log.Fatalf("%s: unexpected sub-symbols", ldr.SymName(s))
2246 }
2247 pos += uint64(ldr.SymSize(s))
2248 if ctxt.IsWindows() {
2249 pos = uint64(Rnd(int64(pos), PEFILEALIGN))
2250 }
2251 }
2252 }
2253 Segdwarf.Length = pos - Segdwarf.Vaddr
2254 }
2255
2256 type compilationUnitByStartPC []*sym.CompilationUnit
2257
2258 func (v compilationUnitByStartPC) Len() int { return len(v) }
2259 func (v compilationUnitByStartPC) Swap(i, j int) { v[i], v[j] = v[j], v[i] }
2260
2261 func (v compilationUnitByStartPC) Less(i, j int) bool {
2262 switch {
2263 case len(v[i].Textp) == 0 && len(v[j].Textp) == 0:
2264 return v[i].Lib.Pkg < v[j].Lib.Pkg
2265 case len(v[i].Textp) != 0 && len(v[j].Textp) == 0:
2266 return true
2267 case len(v[i].Textp) == 0 && len(v[j].Textp) != 0:
2268 return false
2269 default:
2270 return v[i].PCs[0].Start < v[j].PCs[0].Start
2271 }
2272 }
2273
2274
2275
2276
2277
2278 func (d *dwctxt) getPkgFromCUSym(s loader.Sym) string {
2279 return strings.TrimPrefix(d.ldr.SymName(s), dwarf.InfoPrefix+".pkg.")
2280 }
2281
2282
2283
2284
2285
2286
2287 var dwsectCUSizeMu sync.Mutex
2288 var dwsectCUSize map[string]uint64
2289
2290
2291 func getDwsectCUSize(sname string, pkgname string) uint64 {
2292 return dwsectCUSize[sname+"."+pkgname]
2293 }
2294
2295 func addDwsectCUSize(sname string, pkgname string, size uint64) {
2296 dwsectCUSizeMu.Lock()
2297 defer dwsectCUSizeMu.Unlock()
2298 dwsectCUSize[sname+"."+pkgname] += size
2299 }
2300
View as plain text