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