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