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