1
2
3
4
5
6
7
8 package dwarf
9
10 import (
11 "bytes"
12 "errors"
13 "fmt"
14 "internal/buildcfg"
15 exec "internal/execabs"
16 "sort"
17 "strconv"
18 "strings"
19
20 "cmd/internal/objabi"
21 )
22
23
24 const InfoPrefix = "go.info."
25
26
27
28 const ConstInfoPrefix = "go.constinfo."
29
30
31
32 const CUInfoPrefix = "go.cuinfo."
33
34
35
36 const AbstractFuncSuffix = "$abstract"
37
38
39
40 var logDwarf bool
41
42
43 type Sym interface {
44 Length(dwarfContext interface{}) int64
45 }
46
47
48 type Var struct {
49 Name string
50 Abbrev int
51 IsReturnValue bool
52 IsInlFormal bool
53 DictIndex uint16
54 StackOffset int32
55
56
57 PutLocationList func(listSym, startPC Sym)
58 Scope int32
59 Type Sym
60 DeclFile string
61 DeclLine uint
62 DeclCol uint
63 InlIndex int32
64 ChildIndex int32
65 IsInAbstract bool
66 }
67
68
69
70
71
72
73
74 type Scope struct {
75 Parent int32
76 Ranges []Range
77 Vars []*Var
78 }
79
80
81 type Range struct {
82 Start, End int64
83 }
84
85
86
87 type FnState struct {
88 Name string
89 Importpath string
90 Info Sym
91 Filesym Sym
92 Loc Sym
93 Ranges Sym
94 Absfn Sym
95 StartPC Sym
96 Size int64
97 External bool
98 Scopes []Scope
99 InlCalls InlCalls
100 UseBASEntries bool
101
102 dictIndexToOffset []int64
103 }
104
105 func EnableLogging(doit bool) {
106 logDwarf = doit
107 }
108
109
110
111 func MergeRanges(in1, in2 []Range) []Range {
112 out := make([]Range, 0, len(in1)+len(in2))
113 i, j := 0, 0
114 for {
115 var cur Range
116 if i < len(in2) && j < len(in1) {
117 if in2[i].Start < in1[j].Start {
118 cur = in2[i]
119 i++
120 } else {
121 cur = in1[j]
122 j++
123 }
124 } else if i < len(in2) {
125 cur = in2[i]
126 i++
127 } else if j < len(in1) {
128 cur = in1[j]
129 j++
130 } else {
131 break
132 }
133
134 if n := len(out); n > 0 && cur.Start <= out[n-1].End {
135 out[n-1].End = cur.End
136 } else {
137 out = append(out, cur)
138 }
139 }
140
141 return out
142 }
143
144
145 func (s *Scope) UnifyRanges(c *Scope) {
146 s.Ranges = MergeRanges(s.Ranges, c.Ranges)
147 }
148
149
150
151 func (s *Scope) AppendRange(r Range) {
152 if r.End <= r.Start {
153 return
154 }
155 i := len(s.Ranges)
156 if i > 0 && s.Ranges[i-1].End == r.Start {
157 s.Ranges[i-1].End = r.End
158 return
159 }
160 s.Ranges = append(s.Ranges, r)
161 }
162
163 type InlCalls struct {
164 Calls []InlCall
165 }
166
167 type InlCall struct {
168
169 InlIndex int
170
171
172 CallFile Sym
173
174
175 CallLine uint32
176
177
178 AbsFunSym Sym
179
180
181 Children []int
182
183
184
185 InlVars []*Var
186
187
188 Ranges []Range
189
190
191 Root bool
192 }
193
194
195 type Context interface {
196 PtrSize() int
197 AddInt(s Sym, size int, i int64)
198 AddBytes(s Sym, b []byte)
199 AddAddress(s Sym, t interface{}, ofs int64)
200 AddCURelativeAddress(s Sym, t interface{}, ofs int64)
201 AddSectionOffset(s Sym, size int, t interface{}, ofs int64)
202 AddDWARFAddrSectionOffset(s Sym, t interface{}, ofs int64)
203 CurrentOffset(s Sym) int64
204 RecordDclReference(from Sym, to Sym, dclIdx int, inlIndex int)
205 RecordChildDieOffsets(s Sym, vars []*Var, offsets []int32)
206 AddString(s Sym, v string)
207 AddFileRef(s Sym, f interface{})
208 Logf(format string, args ...interface{})
209 }
210
211
212 func AppendUleb128(b []byte, v uint64) []byte {
213 for {
214 c := uint8(v & 0x7f)
215 v >>= 7
216 if v != 0 {
217 c |= 0x80
218 }
219 b = append(b, c)
220 if c&0x80 == 0 {
221 break
222 }
223 }
224 return b
225 }
226
227
228 func AppendSleb128(b []byte, v int64) []byte {
229 for {
230 c := uint8(v & 0x7f)
231 s := uint8(v & 0x40)
232 v >>= 7
233 if (v != -1 || s == 0) && (v != 0 || s != 0) {
234 c |= 0x80
235 }
236 b = append(b, c)
237 if c&0x80 == 0 {
238 break
239 }
240 }
241 return b
242 }
243
244
245 var sevenbits = [...]byte{
246 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
247 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
248 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
249 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
250 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
251 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
252 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
253 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
254 }
255
256
257
258 func sevenBitU(v int64) []byte {
259 if uint64(v) < uint64(len(sevenbits)) {
260 return sevenbits[v : v+1]
261 }
262 return nil
263 }
264
265
266
267 func sevenBitS(v int64) []byte {
268 if uint64(v) <= 63 {
269 return sevenbits[v : v+1]
270 }
271 if uint64(-v) <= 64 {
272 return sevenbits[128+v : 128+v+1]
273 }
274 return nil
275 }
276
277
278 func Uleb128put(ctxt Context, s Sym, v int64) {
279 b := sevenBitU(v)
280 if b == nil {
281 var encbuf [20]byte
282 b = AppendUleb128(encbuf[:0], uint64(v))
283 }
284 ctxt.AddBytes(s, b)
285 }
286
287
288 func Sleb128put(ctxt Context, s Sym, v int64) {
289 b := sevenBitS(v)
290 if b == nil {
291 var encbuf [20]byte
292 b = AppendSleb128(encbuf[:0], v)
293 }
294 ctxt.AddBytes(s, b)
295 }
296
297
305 type dwAttrForm struct {
306 attr uint16
307 form uint8
308 }
309
310
311 const (
312 DW_AT_go_kind = 0x2900
313 DW_AT_go_key = 0x2901
314 DW_AT_go_elem = 0x2902
315
316
317 DW_AT_go_embedded_field = 0x2903
318 DW_AT_go_runtime_type = 0x2904
319
320 DW_AT_go_package_name = 0x2905
321 DW_AT_go_dict_index = 0x2906
322
323 DW_AT_internal_location = 253
324 )
325
326
327 const (
328 DW_ABRV_NULL = iota
329 DW_ABRV_COMPUNIT
330 DW_ABRV_COMPUNIT_TEXTLESS
331 DW_ABRV_FUNCTION
332 DW_ABRV_WRAPPER
333 DW_ABRV_FUNCTION_ABSTRACT
334 DW_ABRV_FUNCTION_CONCRETE
335 DW_ABRV_WRAPPER_CONCRETE
336 DW_ABRV_INLINED_SUBROUTINE
337 DW_ABRV_INLINED_SUBROUTINE_RANGES
338 DW_ABRV_VARIABLE
339 DW_ABRV_INT_CONSTANT
340 DW_ABRV_AUTO
341 DW_ABRV_AUTO_LOCLIST
342 DW_ABRV_AUTO_ABSTRACT
343 DW_ABRV_AUTO_CONCRETE
344 DW_ABRV_AUTO_CONCRETE_LOCLIST
345 DW_ABRV_PARAM
346 DW_ABRV_PARAM_LOCLIST
347 DW_ABRV_PARAM_ABSTRACT
348 DW_ABRV_PARAM_CONCRETE
349 DW_ABRV_PARAM_CONCRETE_LOCLIST
350 DW_ABRV_LEXICAL_BLOCK_RANGES
351 DW_ABRV_LEXICAL_BLOCK_SIMPLE
352 DW_ABRV_STRUCTFIELD
353 DW_ABRV_FUNCTYPEPARAM
354 DW_ABRV_DOTDOTDOT
355 DW_ABRV_ARRAYRANGE
356 DW_ABRV_NULLTYPE
357 DW_ABRV_BASETYPE
358 DW_ABRV_ARRAYTYPE
359 DW_ABRV_CHANTYPE
360 DW_ABRV_FUNCTYPE
361 DW_ABRV_IFACETYPE
362 DW_ABRV_MAPTYPE
363 DW_ABRV_PTRTYPE
364 DW_ABRV_BARE_PTRTYPE
365 DW_ABRV_SLICETYPE
366 DW_ABRV_STRINGTYPE
367 DW_ABRV_STRUCTTYPE
368 DW_ABRV_TYPEDECL
369 DW_ABRV_DICT_INDEX
370 DW_NABRV
371 )
372
373 type dwAbbrev struct {
374 tag uint8
375 children uint8
376 attr []dwAttrForm
377 }
378
379 var abbrevsFinalized bool
380
381
382
383
384
385
386
387 func expandPseudoForm(form uint8) uint8 {
388
389 if form != DW_FORM_udata_pseudo {
390 return form
391 }
392 expandedForm := DW_FORM_udata
393 if buildcfg.GOOS == "darwin" || buildcfg.GOOS == "ios" {
394 expandedForm = DW_FORM_data4
395 }
396 return uint8(expandedForm)
397 }
398
399
400
401 func Abbrevs() []dwAbbrev {
402 if abbrevsFinalized {
403 return abbrevs[:]
404 }
405 for i := 1; i < DW_NABRV; i++ {
406 for j := 0; j < len(abbrevs[i].attr); j++ {
407 abbrevs[i].attr[j].form = expandPseudoForm(abbrevs[i].attr[j].form)
408 }
409 }
410 abbrevsFinalized = true
411 return abbrevs[:]
412 }
413
414
415
416
417
418 var abbrevs = [DW_NABRV]dwAbbrev{
419
420 {0, 0, []dwAttrForm{}},
421
422
423 {
424 DW_TAG_compile_unit,
425 DW_CHILDREN_yes,
426 []dwAttrForm{
427 {DW_AT_name, DW_FORM_string},
428 {DW_AT_language, DW_FORM_data1},
429 {DW_AT_stmt_list, DW_FORM_sec_offset},
430 {DW_AT_low_pc, DW_FORM_addr},
431 {DW_AT_ranges, DW_FORM_sec_offset},
432 {DW_AT_comp_dir, DW_FORM_string},
433 {DW_AT_producer, DW_FORM_string},
434 {DW_AT_go_package_name, DW_FORM_string},
435 },
436 },
437
438
439 {
440 DW_TAG_compile_unit,
441 DW_CHILDREN_yes,
442 []dwAttrForm{
443 {DW_AT_name, DW_FORM_string},
444 {DW_AT_language, DW_FORM_data1},
445 {DW_AT_comp_dir, DW_FORM_string},
446 {DW_AT_producer, DW_FORM_string},
447 {DW_AT_go_package_name, DW_FORM_string},
448 },
449 },
450
451
452 {
453 DW_TAG_subprogram,
454 DW_CHILDREN_yes,
455 []dwAttrForm{
456 {DW_AT_name, DW_FORM_string},
457 {DW_AT_low_pc, DW_FORM_addr},
458 {DW_AT_high_pc, DW_FORM_addr},
459 {DW_AT_frame_base, DW_FORM_block1},
460 {DW_AT_decl_file, DW_FORM_data4},
461 {DW_AT_external, DW_FORM_flag},
462 },
463 },
464
465
466 {
467 DW_TAG_subprogram,
468 DW_CHILDREN_yes,
469 []dwAttrForm{
470 {DW_AT_name, DW_FORM_string},
471 {DW_AT_low_pc, DW_FORM_addr},
472 {DW_AT_high_pc, DW_FORM_addr},
473 {DW_AT_frame_base, DW_FORM_block1},
474 {DW_AT_trampoline, DW_FORM_flag},
475 },
476 },
477
478
479 {
480 DW_TAG_subprogram,
481 DW_CHILDREN_yes,
482 []dwAttrForm{
483 {DW_AT_name, DW_FORM_string},
484 {DW_AT_inline, DW_FORM_data1},
485 {DW_AT_external, DW_FORM_flag},
486 },
487 },
488
489
490 {
491 DW_TAG_subprogram,
492 DW_CHILDREN_yes,
493 []dwAttrForm{
494 {DW_AT_abstract_origin, DW_FORM_ref_addr},
495 {DW_AT_low_pc, DW_FORM_addr},
496 {DW_AT_high_pc, DW_FORM_addr},
497 {DW_AT_frame_base, DW_FORM_block1},
498 },
499 },
500
501
502 {
503 DW_TAG_subprogram,
504 DW_CHILDREN_yes,
505 []dwAttrForm{
506 {DW_AT_abstract_origin, DW_FORM_ref_addr},
507 {DW_AT_low_pc, DW_FORM_addr},
508 {DW_AT_high_pc, DW_FORM_addr},
509 {DW_AT_frame_base, DW_FORM_block1},
510 {DW_AT_trampoline, DW_FORM_flag},
511 },
512 },
513
514
515 {
516 DW_TAG_inlined_subroutine,
517 DW_CHILDREN_yes,
518 []dwAttrForm{
519 {DW_AT_abstract_origin, DW_FORM_ref_addr},
520 {DW_AT_low_pc, DW_FORM_addr},
521 {DW_AT_high_pc, DW_FORM_addr},
522 {DW_AT_call_file, DW_FORM_data4},
523 {DW_AT_call_line, DW_FORM_udata_pseudo},
524 },
525 },
526
527
528 {
529 DW_TAG_inlined_subroutine,
530 DW_CHILDREN_yes,
531 []dwAttrForm{
532 {DW_AT_abstract_origin, DW_FORM_ref_addr},
533 {DW_AT_ranges, DW_FORM_sec_offset},
534 {DW_AT_call_file, DW_FORM_data4},
535 {DW_AT_call_line, DW_FORM_udata_pseudo},
536 },
537 },
538
539
540 {
541 DW_TAG_variable,
542 DW_CHILDREN_no,
543 []dwAttrForm{
544 {DW_AT_name, DW_FORM_string},
545 {DW_AT_location, DW_FORM_block1},
546 {DW_AT_type, DW_FORM_ref_addr},
547 {DW_AT_external, DW_FORM_flag},
548 },
549 },
550
551
552 {
553 DW_TAG_constant,
554 DW_CHILDREN_no,
555 []dwAttrForm{
556 {DW_AT_name, DW_FORM_string},
557 {DW_AT_type, DW_FORM_ref_addr},
558 {DW_AT_const_value, DW_FORM_sdata},
559 },
560 },
561
562
563 {
564 DW_TAG_variable,
565 DW_CHILDREN_no,
566 []dwAttrForm{
567 {DW_AT_name, DW_FORM_string},
568 {DW_AT_decl_line, DW_FORM_udata},
569 {DW_AT_type, DW_FORM_ref_addr},
570 {DW_AT_location, DW_FORM_block1},
571 },
572 },
573
574
575 {
576 DW_TAG_variable,
577 DW_CHILDREN_no,
578 []dwAttrForm{
579 {DW_AT_name, DW_FORM_string},
580 {DW_AT_decl_line, DW_FORM_udata},
581 {DW_AT_type, DW_FORM_ref_addr},
582 {DW_AT_location, DW_FORM_sec_offset},
583 },
584 },
585
586
587 {
588 DW_TAG_variable,
589 DW_CHILDREN_no,
590 []dwAttrForm{
591 {DW_AT_name, DW_FORM_string},
592 {DW_AT_decl_line, DW_FORM_udata},
593 {DW_AT_type, DW_FORM_ref_addr},
594 },
595 },
596
597
598 {
599 DW_TAG_variable,
600 DW_CHILDREN_no,
601 []dwAttrForm{
602 {DW_AT_abstract_origin, DW_FORM_ref_addr},
603 {DW_AT_location, DW_FORM_block1},
604 },
605 },
606
607
608 {
609 DW_TAG_variable,
610 DW_CHILDREN_no,
611 []dwAttrForm{
612 {DW_AT_abstract_origin, DW_FORM_ref_addr},
613 {DW_AT_location, DW_FORM_sec_offset},
614 },
615 },
616
617
618 {
619 DW_TAG_formal_parameter,
620 DW_CHILDREN_no,
621 []dwAttrForm{
622 {DW_AT_name, DW_FORM_string},
623 {DW_AT_variable_parameter, DW_FORM_flag},
624 {DW_AT_decl_line, DW_FORM_udata},
625 {DW_AT_type, DW_FORM_ref_addr},
626 {DW_AT_location, DW_FORM_block1},
627 },
628 },
629
630
631 {
632 DW_TAG_formal_parameter,
633 DW_CHILDREN_no,
634 []dwAttrForm{
635 {DW_AT_name, DW_FORM_string},
636 {DW_AT_variable_parameter, DW_FORM_flag},
637 {DW_AT_decl_line, DW_FORM_udata},
638 {DW_AT_type, DW_FORM_ref_addr},
639 {DW_AT_location, DW_FORM_sec_offset},
640 },
641 },
642
643
644 {
645 DW_TAG_formal_parameter,
646 DW_CHILDREN_no,
647 []dwAttrForm{
648 {DW_AT_name, DW_FORM_string},
649 {DW_AT_variable_parameter, DW_FORM_flag},
650 {DW_AT_type, DW_FORM_ref_addr},
651 },
652 },
653
654
655 {
656 DW_TAG_formal_parameter,
657 DW_CHILDREN_no,
658 []dwAttrForm{
659 {DW_AT_abstract_origin, DW_FORM_ref_addr},
660 {DW_AT_location, DW_FORM_block1},
661 },
662 },
663
664
665 {
666 DW_TAG_formal_parameter,
667 DW_CHILDREN_no,
668 []dwAttrForm{
669 {DW_AT_abstract_origin, DW_FORM_ref_addr},
670 {DW_AT_location, DW_FORM_sec_offset},
671 },
672 },
673
674
675 {
676 DW_TAG_lexical_block,
677 DW_CHILDREN_yes,
678 []dwAttrForm{
679 {DW_AT_ranges, DW_FORM_sec_offset},
680 },
681 },
682
683
684 {
685 DW_TAG_lexical_block,
686 DW_CHILDREN_yes,
687 []dwAttrForm{
688 {DW_AT_low_pc, DW_FORM_addr},
689 {DW_AT_high_pc, DW_FORM_addr},
690 },
691 },
692
693
694 {
695 DW_TAG_member,
696 DW_CHILDREN_no,
697 []dwAttrForm{
698 {DW_AT_name, DW_FORM_string},
699 {DW_AT_data_member_location, DW_FORM_udata},
700 {DW_AT_type, DW_FORM_ref_addr},
701 {DW_AT_go_embedded_field, DW_FORM_flag},
702 },
703 },
704
705
706 {
707 DW_TAG_formal_parameter,
708 DW_CHILDREN_no,
709
710
711 []dwAttrForm{
712 {DW_AT_type, DW_FORM_ref_addr},
713 },
714 },
715
716
717 {
718 DW_TAG_unspecified_parameters,
719 DW_CHILDREN_no,
720 []dwAttrForm{},
721 },
722
723
724 {
725 DW_TAG_subrange_type,
726 DW_CHILDREN_no,
727
728
729 []dwAttrForm{
730 {DW_AT_type, DW_FORM_ref_addr},
731 {DW_AT_count, DW_FORM_udata},
732 },
733 },
734
735
736
737 {
738 DW_TAG_unspecified_type,
739 DW_CHILDREN_no,
740 []dwAttrForm{
741 {DW_AT_name, DW_FORM_string},
742 },
743 },
744
745
746 {
747 DW_TAG_base_type,
748 DW_CHILDREN_no,
749 []dwAttrForm{
750 {DW_AT_name, DW_FORM_string},
751 {DW_AT_encoding, DW_FORM_data1},
752 {DW_AT_byte_size, DW_FORM_data1},
753 {DW_AT_go_kind, DW_FORM_data1},
754 {DW_AT_go_runtime_type, DW_FORM_addr},
755 },
756 },
757
758
759
760 {
761 DW_TAG_array_type,
762 DW_CHILDREN_yes,
763 []dwAttrForm{
764 {DW_AT_name, DW_FORM_string},
765 {DW_AT_type, DW_FORM_ref_addr},
766 {DW_AT_byte_size, DW_FORM_udata},
767 {DW_AT_go_kind, DW_FORM_data1},
768 {DW_AT_go_runtime_type, DW_FORM_addr},
769 },
770 },
771
772
773 {
774 DW_TAG_typedef,
775 DW_CHILDREN_no,
776 []dwAttrForm{
777 {DW_AT_name, DW_FORM_string},
778 {DW_AT_type, DW_FORM_ref_addr},
779 {DW_AT_go_kind, DW_FORM_data1},
780 {DW_AT_go_runtime_type, DW_FORM_addr},
781 {DW_AT_go_elem, DW_FORM_ref_addr},
782 },
783 },
784
785
786 {
787 DW_TAG_subroutine_type,
788 DW_CHILDREN_yes,
789 []dwAttrForm{
790 {DW_AT_name, DW_FORM_string},
791 {DW_AT_byte_size, DW_FORM_udata},
792 {DW_AT_go_kind, DW_FORM_data1},
793 {DW_AT_go_runtime_type, DW_FORM_addr},
794 },
795 },
796
797
798 {
799 DW_TAG_typedef,
800 DW_CHILDREN_yes,
801 []dwAttrForm{
802 {DW_AT_name, DW_FORM_string},
803 {DW_AT_type, DW_FORM_ref_addr},
804 {DW_AT_go_kind, DW_FORM_data1},
805 {DW_AT_go_runtime_type, DW_FORM_addr},
806 },
807 },
808
809
810 {
811 DW_TAG_typedef,
812 DW_CHILDREN_no,
813 []dwAttrForm{
814 {DW_AT_name, DW_FORM_string},
815 {DW_AT_type, DW_FORM_ref_addr},
816 {DW_AT_go_kind, DW_FORM_data1},
817 {DW_AT_go_runtime_type, DW_FORM_addr},
818 {DW_AT_go_key, DW_FORM_ref_addr},
819 {DW_AT_go_elem, DW_FORM_ref_addr},
820 },
821 },
822
823
824 {
825 DW_TAG_pointer_type,
826 DW_CHILDREN_no,
827 []dwAttrForm{
828 {DW_AT_name, DW_FORM_string},
829 {DW_AT_type, DW_FORM_ref_addr},
830 {DW_AT_go_kind, DW_FORM_data1},
831 {DW_AT_go_runtime_type, DW_FORM_addr},
832 },
833 },
834
835
836 {
837 DW_TAG_pointer_type,
838 DW_CHILDREN_no,
839 []dwAttrForm{
840 {DW_AT_name, DW_FORM_string},
841 },
842 },
843
844
845 {
846 DW_TAG_structure_type,
847 DW_CHILDREN_yes,
848 []dwAttrForm{
849 {DW_AT_name, DW_FORM_string},
850 {DW_AT_byte_size, DW_FORM_udata},
851 {DW_AT_go_kind, DW_FORM_data1},
852 {DW_AT_go_runtime_type, DW_FORM_addr},
853 {DW_AT_go_elem, DW_FORM_ref_addr},
854 },
855 },
856
857
858 {
859 DW_TAG_structure_type,
860 DW_CHILDREN_yes,
861 []dwAttrForm{
862 {DW_AT_name, DW_FORM_string},
863 {DW_AT_byte_size, DW_FORM_udata},
864 {DW_AT_go_kind, DW_FORM_data1},
865 {DW_AT_go_runtime_type, DW_FORM_addr},
866 },
867 },
868
869
870 {
871 DW_TAG_structure_type,
872 DW_CHILDREN_yes,
873 []dwAttrForm{
874 {DW_AT_name, DW_FORM_string},
875 {DW_AT_byte_size, DW_FORM_udata},
876 {DW_AT_go_kind, DW_FORM_data1},
877 {DW_AT_go_runtime_type, DW_FORM_addr},
878 },
879 },
880
881
882 {
883 DW_TAG_typedef,
884 DW_CHILDREN_no,
885 []dwAttrForm{
886 {DW_AT_name, DW_FORM_string},
887 {DW_AT_type, DW_FORM_ref_addr},
888 },
889 },
890
891
892 {
893 DW_TAG_typedef,
894 DW_CHILDREN_no,
895 []dwAttrForm{
896 {DW_AT_name, DW_FORM_string},
897 {DW_AT_type, DW_FORM_ref_addr},
898 {DW_AT_go_dict_index, DW_FORM_udata},
899 },
900 },
901 }
902
903
904 func GetAbbrev() []byte {
905 abbrevs := Abbrevs()
906 var buf []byte
907 for i := 1; i < DW_NABRV; i++ {
908
909 buf = AppendUleb128(buf, uint64(i))
910 buf = AppendUleb128(buf, uint64(abbrevs[i].tag))
911 buf = append(buf, abbrevs[i].children)
912 for _, f := range abbrevs[i].attr {
913 buf = AppendUleb128(buf, uint64(f.attr))
914 buf = AppendUleb128(buf, uint64(f.form))
915 }
916 buf = append(buf, 0, 0)
917 }
918 return append(buf, 0)
919 }
920
921
924
925
926
927
928
929
930
931 type DWAttr struct {
932 Link *DWAttr
933 Atr uint16
934 Cls uint8
935 Value int64
936 Data interface{}
937 }
938
939
940 type DWDie struct {
941 Abbrev int
942 Link *DWDie
943 Child *DWDie
944 Attr *DWAttr
945 Sym Sym
946 }
947
948 func putattr(ctxt Context, s Sym, abbrev int, form int, cls int, value int64, data interface{}) error {
949 switch form {
950 case DW_FORM_addr:
951
952 if data == nil && value == 0 {
953 ctxt.AddInt(s, ctxt.PtrSize(), 0)
954 break
955 }
956 if cls == DW_CLS_GO_TYPEREF {
957 ctxt.AddSectionOffset(s, ctxt.PtrSize(), data, value)
958 break
959 }
960 ctxt.AddAddress(s, data, value)
961
962 case DW_FORM_block1:
963 if cls == DW_CLS_ADDRESS {
964 ctxt.AddInt(s, 1, int64(1+ctxt.PtrSize()))
965 ctxt.AddInt(s, 1, DW_OP_addr)
966 ctxt.AddAddress(s, data, 0)
967 break
968 }
969
970 value &= 0xff
971 ctxt.AddInt(s, 1, value)
972 p := data.([]byte)[:value]
973 ctxt.AddBytes(s, p)
974
975 case DW_FORM_block2:
976 value &= 0xffff
977
978 ctxt.AddInt(s, 2, value)
979 p := data.([]byte)[:value]
980 ctxt.AddBytes(s, p)
981
982 case DW_FORM_block4:
983 value &= 0xffffffff
984
985 ctxt.AddInt(s, 4, value)
986 p := data.([]byte)[:value]
987 ctxt.AddBytes(s, p)
988
989 case DW_FORM_block:
990 Uleb128put(ctxt, s, value)
991
992 p := data.([]byte)[:value]
993 ctxt.AddBytes(s, p)
994
995 case DW_FORM_data1:
996 ctxt.AddInt(s, 1, value)
997
998 case DW_FORM_data2:
999 ctxt.AddInt(s, 2, value)
1000
1001 case DW_FORM_data4:
1002 if cls == DW_CLS_PTR {
1003 ctxt.AddDWARFAddrSectionOffset(s, data, value)
1004 break
1005 }
1006 ctxt.AddInt(s, 4, value)
1007
1008 case DW_FORM_data8:
1009 ctxt.AddInt(s, 8, value)
1010
1011 case DW_FORM_sdata:
1012 Sleb128put(ctxt, s, value)
1013
1014 case DW_FORM_udata:
1015 Uleb128put(ctxt, s, value)
1016
1017 case DW_FORM_string:
1018 str := data.(string)
1019 ctxt.AddString(s, str)
1020
1021 for i := int64(len(str)); i < value; i++ {
1022 ctxt.AddInt(s, 1, 0)
1023 }
1024
1025 case DW_FORM_flag:
1026 if value != 0 {
1027 ctxt.AddInt(s, 1, 1)
1028 } else {
1029 ctxt.AddInt(s, 1, 0)
1030 }
1031
1032
1033
1034 case DW_FORM_ref_addr:
1035 fallthrough
1036 case DW_FORM_sec_offset:
1037 if data == nil {
1038 return fmt.Errorf("dwarf: null reference in %d", abbrev)
1039 }
1040 ctxt.AddDWARFAddrSectionOffset(s, data, value)
1041
1042 case DW_FORM_ref1,
1043 DW_FORM_ref2,
1044 DW_FORM_ref4,
1045 DW_FORM_ref8,
1046 DW_FORM_ref_udata,
1047
1048 DW_FORM_strp,
1049 DW_FORM_indirect:
1050 fallthrough
1051 default:
1052 return fmt.Errorf("dwarf: unsupported attribute form %d / class %d", form, cls)
1053 }
1054 return nil
1055 }
1056
1057
1058
1059
1060
1061 func PutAttrs(ctxt Context, s Sym, abbrev int, attr *DWAttr) {
1062 abbrevs := Abbrevs()
1063 Outer:
1064 for _, f := range abbrevs[abbrev].attr {
1065 for ap := attr; ap != nil; ap = ap.Link {
1066 if ap.Atr == f.attr {
1067 putattr(ctxt, s, abbrev, int(f.form), int(ap.Cls), ap.Value, ap.Data)
1068 continue Outer
1069 }
1070 }
1071
1072 putattr(ctxt, s, abbrev, int(f.form), 0, 0, nil)
1073 }
1074 }
1075
1076
1077 func HasChildren(die *DWDie) bool {
1078 abbrevs := Abbrevs()
1079 return abbrevs[die.Abbrev].children != 0
1080 }
1081
1082
1083 func PutIntConst(ctxt Context, info, typ Sym, name string, val int64) {
1084 Uleb128put(ctxt, info, DW_ABRV_INT_CONSTANT)
1085 putattr(ctxt, info, DW_ABRV_INT_CONSTANT, DW_FORM_string, DW_CLS_STRING, int64(len(name)), name)
1086 putattr(ctxt, info, DW_ABRV_INT_CONSTANT, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, typ)
1087 putattr(ctxt, info, DW_ABRV_INT_CONSTANT, DW_FORM_sdata, DW_CLS_CONSTANT, val, nil)
1088 }
1089
1090
1091 func PutGlobal(ctxt Context, info, typ, gvar Sym, name string) {
1092 Uleb128put(ctxt, info, DW_ABRV_VARIABLE)
1093 putattr(ctxt, info, DW_ABRV_VARIABLE, DW_FORM_string, DW_CLS_STRING, int64(len(name)), name)
1094 putattr(ctxt, info, DW_ABRV_VARIABLE, DW_FORM_block1, DW_CLS_ADDRESS, 0, gvar)
1095 putattr(ctxt, info, DW_ABRV_VARIABLE, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, typ)
1096 putattr(ctxt, info, DW_ABRV_VARIABLE, DW_FORM_flag, DW_CLS_FLAG, 1, nil)
1097 }
1098
1099
1100
1101
1102 func PutBasedRanges(ctxt Context, sym Sym, ranges []Range) {
1103 ps := ctxt.PtrSize()
1104
1105 for _, r := range ranges {
1106 ctxt.AddInt(sym, ps, r.Start)
1107 ctxt.AddInt(sym, ps, r.End)
1108 }
1109
1110 ctxt.AddInt(sym, ps, 0)
1111 ctxt.AddInt(sym, ps, 0)
1112 }
1113
1114
1115
1116 func (s *FnState) PutRanges(ctxt Context, ranges []Range) {
1117 ps := ctxt.PtrSize()
1118 sym, base := s.Ranges, s.StartPC
1119
1120 if s.UseBASEntries {
1121
1122
1123 ctxt.AddInt(sym, ps, -1)
1124 ctxt.AddAddress(sym, base, 0)
1125 PutBasedRanges(ctxt, sym, ranges)
1126 return
1127 }
1128
1129
1130 for _, r := range ranges {
1131 ctxt.AddCURelativeAddress(sym, base, r.Start)
1132 ctxt.AddCURelativeAddress(sym, base, r.End)
1133 }
1134
1135 ctxt.AddInt(sym, ps, 0)
1136 ctxt.AddInt(sym, ps, 0)
1137 }
1138
1139
1140
1141
1142 func isEmptyInlinedCall(slot int, calls *InlCalls) bool {
1143 ic := &calls.Calls[slot]
1144 if ic.InlIndex == -2 {
1145 return true
1146 }
1147 live := false
1148 for _, k := range ic.Children {
1149 if !isEmptyInlinedCall(k, calls) {
1150 live = true
1151 }
1152 }
1153 if len(ic.Ranges) > 0 {
1154 live = true
1155 }
1156 if !live {
1157 ic.InlIndex = -2
1158 }
1159 return !live
1160 }
1161
1162
1163
1164 func inlChildren(slot int, calls *InlCalls) []int {
1165 var kids []int
1166 if slot != -1 {
1167 for _, k := range calls.Calls[slot].Children {
1168 if !isEmptyInlinedCall(k, calls) {
1169 kids = append(kids, k)
1170 }
1171 }
1172 } else {
1173 for k := 0; k < len(calls.Calls); k += 1 {
1174 if calls.Calls[k].Root && !isEmptyInlinedCall(k, calls) {
1175 kids = append(kids, k)
1176 }
1177 }
1178 }
1179 return kids
1180 }
1181
1182 func inlinedVarTable(inlcalls *InlCalls) map[*Var]bool {
1183 vars := make(map[*Var]bool)
1184 for _, ic := range inlcalls.Calls {
1185 for _, v := range ic.InlVars {
1186 vars[v] = true
1187 }
1188 }
1189 return vars
1190 }
1191
1192
1193
1194
1195
1196
1197
1198 func putPrunedScopes(ctxt Context, s *FnState, fnabbrev int) error {
1199 if len(s.Scopes) == 0 {
1200 return nil
1201 }
1202 scopes := make([]Scope, len(s.Scopes), len(s.Scopes))
1203 pvars := inlinedVarTable(&s.InlCalls)
1204 for k, s := range s.Scopes {
1205 var pruned Scope = Scope{Parent: s.Parent, Ranges: s.Ranges}
1206 for i := 0; i < len(s.Vars); i++ {
1207 _, found := pvars[s.Vars[i]]
1208 if !found {
1209 pruned.Vars = append(pruned.Vars, s.Vars[i])
1210 }
1211 }
1212 sort.Sort(byChildIndex(pruned.Vars))
1213 scopes[k] = pruned
1214 }
1215
1216 s.dictIndexToOffset = putparamtypes(ctxt, s, scopes, fnabbrev)
1217
1218 var encbuf [20]byte
1219 if putscope(ctxt, s, scopes, 0, fnabbrev, encbuf[:0]) < int32(len(scopes)) {
1220 return errors.New("multiple toplevel scopes")
1221 }
1222 return nil
1223 }
1224
1225
1226
1227
1228
1229
1230
1231
1232 func PutAbstractFunc(ctxt Context, s *FnState) error {
1233
1234 if logDwarf {
1235 ctxt.Logf("PutAbstractFunc(%v)\n", s.Absfn)
1236 }
1237
1238 abbrev := DW_ABRV_FUNCTION_ABSTRACT
1239 Uleb128put(ctxt, s.Absfn, int64(abbrev))
1240
1241 fullname := s.Name
1242 if strings.HasPrefix(s.Name, "\"\".") {
1243
1244
1245
1246
1247
1248
1249
1250 fullname = objabi.PathToPrefix(s.Importpath) + "." + s.Name[3:]
1251 }
1252 putattr(ctxt, s.Absfn, abbrev, DW_FORM_string, DW_CLS_STRING, int64(len(fullname)), fullname)
1253
1254
1255 putattr(ctxt, s.Absfn, abbrev, DW_FORM_data1, DW_CLS_CONSTANT, int64(DW_INL_inlined), nil)
1256
1257 var ev int64
1258 if s.External {
1259 ev = 1
1260 }
1261 putattr(ctxt, s.Absfn, abbrev, DW_FORM_flag, DW_CLS_FLAG, ev, 0)
1262
1263
1264 var flattened []*Var
1265
1266
1267
1268 var offsets []int32
1269
1270
1271 if len(s.Scopes) > 0 {
1272
1273
1274
1275 pvars := inlinedVarTable(&s.InlCalls)
1276 for _, scope := range s.Scopes {
1277 for i := 0; i < len(scope.Vars); i++ {
1278 _, found := pvars[scope.Vars[i]]
1279 if found || !scope.Vars[i].IsInAbstract {
1280 continue
1281 }
1282 flattened = append(flattened, scope.Vars[i])
1283 }
1284 }
1285 if len(flattened) > 0 {
1286 sort.Sort(byChildIndex(flattened))
1287
1288 if logDwarf {
1289 ctxt.Logf("putAbstractScope(%v): vars:", s.Info)
1290 for i, v := range flattened {
1291 ctxt.Logf(" %d:%s", i, v.Name)
1292 }
1293 ctxt.Logf("\n")
1294 }
1295
1296
1297
1298
1299 for _, v := range flattened {
1300 offsets = append(offsets, int32(ctxt.CurrentOffset(s.Absfn)))
1301 putAbstractVar(ctxt, s.Absfn, v)
1302 }
1303 }
1304 }
1305 ctxt.RecordChildDieOffsets(s.Absfn, flattened, offsets)
1306
1307 Uleb128put(ctxt, s.Absfn, 0)
1308 return nil
1309 }
1310
1311
1312
1313
1314
1315
1316 func putInlinedFunc(ctxt Context, s *FnState, callIdx int) error {
1317 ic := s.InlCalls.Calls[callIdx]
1318 callee := ic.AbsFunSym
1319
1320 abbrev := DW_ABRV_INLINED_SUBROUTINE_RANGES
1321 if len(ic.Ranges) == 1 {
1322 abbrev = DW_ABRV_INLINED_SUBROUTINE
1323 }
1324 Uleb128put(ctxt, s.Info, int64(abbrev))
1325
1326 if logDwarf {
1327 ctxt.Logf("putInlinedFunc(callee=%v,abbrev=%d)\n", callee, abbrev)
1328 }
1329
1330
1331 putattr(ctxt, s.Info, abbrev, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, callee)
1332
1333 if abbrev == DW_ABRV_INLINED_SUBROUTINE_RANGES {
1334 putattr(ctxt, s.Info, abbrev, DW_FORM_sec_offset, DW_CLS_PTR, s.Ranges.Length(ctxt), s.Ranges)
1335 s.PutRanges(ctxt, ic.Ranges)
1336 } else {
1337 st := ic.Ranges[0].Start
1338 en := ic.Ranges[0].End
1339 putattr(ctxt, s.Info, abbrev, DW_FORM_addr, DW_CLS_ADDRESS, st, s.StartPC)
1340 putattr(ctxt, s.Info, abbrev, DW_FORM_addr, DW_CLS_ADDRESS, en, s.StartPC)
1341 }
1342
1343
1344 ctxt.AddFileRef(s.Info, ic.CallFile)
1345 form := int(expandPseudoForm(DW_FORM_udata_pseudo))
1346 putattr(ctxt, s.Info, abbrev, form, DW_CLS_CONSTANT, int64(ic.CallLine), nil)
1347
1348
1349 vars := ic.InlVars
1350 sort.Sort(byChildIndex(vars))
1351 inlIndex := ic.InlIndex
1352 var encbuf [20]byte
1353 for _, v := range vars {
1354 if !v.IsInAbstract {
1355 continue
1356 }
1357 putvar(ctxt, s, v, callee, abbrev, inlIndex, encbuf[:0])
1358 }
1359
1360
1361 for _, sib := range inlChildren(callIdx, &s.InlCalls) {
1362 err := putInlinedFunc(ctxt, s, sib)
1363 if err != nil {
1364 return err
1365 }
1366 }
1367
1368 Uleb128put(ctxt, s.Info, 0)
1369 return nil
1370 }
1371
1372
1373
1374
1375
1376
1377
1378
1379 func PutConcreteFunc(ctxt Context, s *FnState, isWrapper bool) error {
1380 if logDwarf {
1381 ctxt.Logf("PutConcreteFunc(%v)\n", s.Info)
1382 }
1383 abbrev := DW_ABRV_FUNCTION_CONCRETE
1384 if isWrapper {
1385 abbrev = DW_ABRV_WRAPPER_CONCRETE
1386 }
1387 Uleb128put(ctxt, s.Info, int64(abbrev))
1388
1389
1390 putattr(ctxt, s.Info, abbrev, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, s.Absfn)
1391
1392
1393 putattr(ctxt, s.Info, abbrev, DW_FORM_addr, DW_CLS_ADDRESS, 0, s.StartPC)
1394 putattr(ctxt, s.Info, abbrev, DW_FORM_addr, DW_CLS_ADDRESS, s.Size, s.StartPC)
1395
1396
1397 putattr(ctxt, s.Info, abbrev, DW_FORM_block1, DW_CLS_BLOCK, 1, []byte{DW_OP_call_frame_cfa})
1398
1399 if isWrapper {
1400 putattr(ctxt, s.Info, abbrev, DW_FORM_flag, DW_CLS_FLAG, int64(1), 0)
1401 }
1402
1403
1404 if err := putPrunedScopes(ctxt, s, abbrev); err != nil {
1405 return err
1406 }
1407
1408
1409 for _, sib := range inlChildren(-1, &s.InlCalls) {
1410 err := putInlinedFunc(ctxt, s, sib)
1411 if err != nil {
1412 return err
1413 }
1414 }
1415
1416 Uleb128put(ctxt, s.Info, 0)
1417 return nil
1418 }
1419
1420
1421
1422
1423
1424
1425 func PutDefaultFunc(ctxt Context, s *FnState, isWrapper bool) error {
1426 if logDwarf {
1427 ctxt.Logf("PutDefaultFunc(%v)\n", s.Info)
1428 }
1429 abbrev := DW_ABRV_FUNCTION
1430 if isWrapper {
1431 abbrev = DW_ABRV_WRAPPER
1432 }
1433 Uleb128put(ctxt, s.Info, int64(abbrev))
1434
1435
1436 name := s.Name
1437 if s.Importpath != "" {
1438 name = strings.Replace(name, "\"\".", objabi.PathToPrefix(s.Importpath)+".", -1)
1439 }
1440
1441 putattr(ctxt, s.Info, DW_ABRV_FUNCTION, DW_FORM_string, DW_CLS_STRING, int64(len(name)), name)
1442 putattr(ctxt, s.Info, abbrev, DW_FORM_addr, DW_CLS_ADDRESS, 0, s.StartPC)
1443 putattr(ctxt, s.Info, abbrev, DW_FORM_addr, DW_CLS_ADDRESS, s.Size, s.StartPC)
1444 putattr(ctxt, s.Info, abbrev, DW_FORM_block1, DW_CLS_BLOCK, 1, []byte{DW_OP_call_frame_cfa})
1445 if isWrapper {
1446 putattr(ctxt, s.Info, abbrev, DW_FORM_flag, DW_CLS_FLAG, int64(1), 0)
1447 } else {
1448 ctxt.AddFileRef(s.Info, s.Filesym)
1449 var ev int64
1450 if s.External {
1451 ev = 1
1452 }
1453 putattr(ctxt, s.Info, abbrev, DW_FORM_flag, DW_CLS_FLAG, ev, 0)
1454 }
1455
1456
1457 if err := putPrunedScopes(ctxt, s, abbrev); err != nil {
1458 return err
1459 }
1460
1461
1462 for _, sib := range inlChildren(-1, &s.InlCalls) {
1463 err := putInlinedFunc(ctxt, s, sib)
1464 if err != nil {
1465 return err
1466 }
1467 }
1468
1469 Uleb128put(ctxt, s.Info, 0)
1470 return nil
1471 }
1472
1473
1474 func putparamtypes(ctxt Context, s *FnState, scopes []Scope, fnabbrev int) []int64 {
1475 if fnabbrev == DW_ABRV_FUNCTION_CONCRETE {
1476 return nil
1477 }
1478
1479 maxDictIndex := uint16(0)
1480
1481 for i := range scopes {
1482 for _, v := range scopes[i].Vars {
1483 if v.DictIndex > maxDictIndex {
1484 maxDictIndex = v.DictIndex
1485 }
1486 }
1487 }
1488
1489 if maxDictIndex == 0 {
1490 return nil
1491 }
1492
1493 dictIndexToOffset := make([]int64, maxDictIndex)
1494
1495 for i := range scopes {
1496 for _, v := range scopes[i].Vars {
1497 if v.DictIndex == 0 || dictIndexToOffset[v.DictIndex-1] != 0 {
1498 continue
1499 }
1500
1501 dictIndexToOffset[v.DictIndex-1] = ctxt.CurrentOffset(s.Info)
1502
1503 Uleb128put(ctxt, s.Info, int64(DW_ABRV_DICT_INDEX))
1504 n := fmt.Sprintf(".param%d", v.DictIndex-1)
1505 putattr(ctxt, s.Info, DW_ABRV_DICT_INDEX, DW_FORM_string, DW_CLS_STRING, int64(len(n)), n)
1506 putattr(ctxt, s.Info, DW_ABRV_DICT_INDEX, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, v.Type)
1507 putattr(ctxt, s.Info, DW_ABRV_DICT_INDEX, DW_FORM_udata, DW_CLS_CONSTANT, int64(v.DictIndex-1), nil)
1508 }
1509 }
1510
1511 return dictIndexToOffset
1512 }
1513
1514 func putscope(ctxt Context, s *FnState, scopes []Scope, curscope int32, fnabbrev int, encbuf []byte) int32 {
1515
1516 if logDwarf {
1517 ctxt.Logf("putscope(%v,%d): vars:", s.Info, curscope)
1518 for i, v := range scopes[curscope].Vars {
1519 ctxt.Logf(" %d:%d:%s", i, v.ChildIndex, v.Name)
1520 }
1521 ctxt.Logf("\n")
1522 }
1523
1524 for _, v := range scopes[curscope].Vars {
1525 putvar(ctxt, s, v, s.Absfn, fnabbrev, -1, encbuf)
1526 }
1527 this := curscope
1528 curscope++
1529 for curscope < int32(len(scopes)) {
1530 scope := scopes[curscope]
1531 if scope.Parent != this {
1532 return curscope
1533 }
1534
1535 if len(scopes[curscope].Vars) == 0 {
1536 curscope = putscope(ctxt, s, scopes, curscope, fnabbrev, encbuf)
1537 continue
1538 }
1539
1540 if len(scope.Ranges) == 1 {
1541 Uleb128put(ctxt, s.Info, DW_ABRV_LEXICAL_BLOCK_SIMPLE)
1542 putattr(ctxt, s.Info, DW_ABRV_LEXICAL_BLOCK_SIMPLE, DW_FORM_addr, DW_CLS_ADDRESS, scope.Ranges[0].Start, s.StartPC)
1543 putattr(ctxt, s.Info, DW_ABRV_LEXICAL_BLOCK_SIMPLE, DW_FORM_addr, DW_CLS_ADDRESS, scope.Ranges[0].End, s.StartPC)
1544 } else {
1545 Uleb128put(ctxt, s.Info, DW_ABRV_LEXICAL_BLOCK_RANGES)
1546 putattr(ctxt, s.Info, DW_ABRV_LEXICAL_BLOCK_RANGES, DW_FORM_sec_offset, DW_CLS_PTR, s.Ranges.Length(ctxt), s.Ranges)
1547
1548 s.PutRanges(ctxt, scope.Ranges)
1549 }
1550
1551 curscope = putscope(ctxt, s, scopes, curscope, fnabbrev, encbuf)
1552
1553 Uleb128put(ctxt, s.Info, 0)
1554 }
1555 return curscope
1556 }
1557
1558
1559 func concreteVarAbbrev(varAbbrev int) int {
1560 switch varAbbrev {
1561 case DW_ABRV_AUTO:
1562 return DW_ABRV_AUTO_CONCRETE
1563 case DW_ABRV_PARAM:
1564 return DW_ABRV_PARAM_CONCRETE
1565 case DW_ABRV_AUTO_LOCLIST:
1566 return DW_ABRV_AUTO_CONCRETE_LOCLIST
1567 case DW_ABRV_PARAM_LOCLIST:
1568 return DW_ABRV_PARAM_CONCRETE_LOCLIST
1569 default:
1570 panic("should never happen")
1571 }
1572 }
1573
1574
1575 func determineVarAbbrev(v *Var, fnabbrev int) (int, bool, bool) {
1576 abbrev := v.Abbrev
1577
1578
1579
1580 missing := false
1581 switch {
1582 case abbrev == DW_ABRV_AUTO_LOCLIST && v.PutLocationList == nil:
1583 missing = true
1584 abbrev = DW_ABRV_AUTO
1585 case abbrev == DW_ABRV_PARAM_LOCLIST && v.PutLocationList == nil:
1586 missing = true
1587 abbrev = DW_ABRV_PARAM
1588 }
1589
1590
1591 concrete := true
1592 switch fnabbrev {
1593 case DW_ABRV_FUNCTION, DW_ABRV_WRAPPER:
1594 concrete = false
1595 break
1596 case DW_ABRV_FUNCTION_CONCRETE, DW_ABRV_WRAPPER_CONCRETE:
1597
1598
1599
1600 if !v.IsInAbstract {
1601 concrete = false
1602 }
1603 case DW_ABRV_INLINED_SUBROUTINE, DW_ABRV_INLINED_SUBROUTINE_RANGES:
1604 default:
1605 panic("should never happen")
1606 }
1607
1608
1609 if concrete {
1610 abbrev = concreteVarAbbrev(abbrev)
1611 }
1612
1613 return abbrev, missing, concrete
1614 }
1615
1616 func abbrevUsesLoclist(abbrev int) bool {
1617 switch abbrev {
1618 case DW_ABRV_AUTO_LOCLIST, DW_ABRV_AUTO_CONCRETE_LOCLIST,
1619 DW_ABRV_PARAM_LOCLIST, DW_ABRV_PARAM_CONCRETE_LOCLIST:
1620 return true
1621 default:
1622 return false
1623 }
1624 }
1625
1626
1627 func putAbstractVar(ctxt Context, info Sym, v *Var) {
1628
1629 abbrev := v.Abbrev
1630 switch abbrev {
1631 case DW_ABRV_AUTO, DW_ABRV_AUTO_LOCLIST:
1632 abbrev = DW_ABRV_AUTO_ABSTRACT
1633 case DW_ABRV_PARAM, DW_ABRV_PARAM_LOCLIST:
1634 abbrev = DW_ABRV_PARAM_ABSTRACT
1635 }
1636
1637 Uleb128put(ctxt, info, int64(abbrev))
1638 putattr(ctxt, info, abbrev, DW_FORM_string, DW_CLS_STRING, int64(len(v.Name)), v.Name)
1639
1640
1641 if abbrev == DW_ABRV_PARAM_ABSTRACT {
1642 var isReturn int64
1643 if v.IsReturnValue {
1644 isReturn = 1
1645 }
1646 putattr(ctxt, info, abbrev, DW_FORM_flag, DW_CLS_FLAG, isReturn, nil)
1647 }
1648
1649
1650 if abbrev != DW_ABRV_PARAM_ABSTRACT {
1651
1652 putattr(ctxt, info, abbrev, DW_FORM_udata, DW_CLS_CONSTANT, int64(v.DeclLine), nil)
1653 }
1654
1655
1656 putattr(ctxt, info, abbrev, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, v.Type)
1657
1658
1659 }
1660
1661 func putvar(ctxt Context, s *FnState, v *Var, absfn Sym, fnabbrev, inlIndex int, encbuf []byte) {
1662
1663 abbrev, missing, concrete := determineVarAbbrev(v, fnabbrev)
1664
1665 Uleb128put(ctxt, s.Info, int64(abbrev))
1666
1667
1668 if concrete {
1669
1670
1671
1672
1673 putattr(ctxt, s.Info, abbrev, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, absfn)
1674 ctxt.RecordDclReference(s.Info, absfn, int(v.ChildIndex), inlIndex)
1675 } else {
1676
1677 n := v.Name
1678 putattr(ctxt, s.Info, abbrev, DW_FORM_string, DW_CLS_STRING, int64(len(n)), n)
1679 if abbrev == DW_ABRV_PARAM || abbrev == DW_ABRV_PARAM_LOCLIST || abbrev == DW_ABRV_PARAM_ABSTRACT {
1680 var isReturn int64
1681 if v.IsReturnValue {
1682 isReturn = 1
1683 }
1684 putattr(ctxt, s.Info, abbrev, DW_FORM_flag, DW_CLS_FLAG, isReturn, nil)
1685 }
1686 putattr(ctxt, s.Info, abbrev, DW_FORM_udata, DW_CLS_CONSTANT, int64(v.DeclLine), nil)
1687 if v.DictIndex > 0 && s.dictIndexToOffset != nil && s.dictIndexToOffset[v.DictIndex-1] != 0 {
1688
1689 putattr(ctxt, s.Info, abbrev, DW_FORM_ref_addr, DW_CLS_REFERENCE, s.dictIndexToOffset[v.DictIndex-1], s.Info)
1690 } else {
1691 putattr(ctxt, s.Info, abbrev, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, v.Type)
1692 }
1693 }
1694
1695 if abbrevUsesLoclist(abbrev) {
1696 putattr(ctxt, s.Info, abbrev, DW_FORM_sec_offset, DW_CLS_PTR, s.Loc.Length(ctxt), s.Loc)
1697 v.PutLocationList(s.Loc, s.StartPC)
1698 } else {
1699 loc := encbuf[:0]
1700 switch {
1701 case missing:
1702 break
1703 case v.StackOffset == 0:
1704 loc = append(loc, DW_OP_call_frame_cfa)
1705 default:
1706 loc = append(loc, DW_OP_fbreg)
1707 loc = AppendSleb128(loc, int64(v.StackOffset))
1708 }
1709 putattr(ctxt, s.Info, abbrev, DW_FORM_block1, DW_CLS_BLOCK, int64(len(loc)), loc)
1710 }
1711
1712
1713 }
1714
1715
1716 type byChildIndex []*Var
1717
1718 func (s byChildIndex) Len() int { return len(s) }
1719 func (s byChildIndex) Less(i, j int) bool { return s[i].ChildIndex < s[j].ChildIndex }
1720 func (s byChildIndex) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
1721
1722
1723
1724
1725
1726 func IsDWARFEnabledOnAIXLd(extld []string) (bool, error) {
1727 name, args := extld[0], extld[1:]
1728 args = append(args, "-Wl,-V")
1729 out, err := exec.Command(name, args...).CombinedOutput()
1730 if err != nil {
1731
1732
1733
1734 if !bytes.Contains(out, []byte("0711-317")) {
1735 return false, fmt.Errorf("%s -Wl,-V failed: %v\n%s", extld, err, out)
1736 }
1737 }
1738
1739
1740
1741 out = bytes.TrimPrefix(out, []byte("/usr/bin/ld: LD "))
1742 vers := string(bytes.Split(out, []byte("("))[0])
1743 subvers := strings.Split(vers, ".")
1744 if len(subvers) != 3 {
1745 return false, fmt.Errorf("cannot parse %s -Wl,-V (%s): %v\n", extld, out, err)
1746 }
1747 if v, err := strconv.Atoi(subvers[0]); err != nil || v < 7 {
1748 return false, nil
1749 } else if v > 7 {
1750 return true, nil
1751 }
1752 if v, err := strconv.Atoi(subvers[1]); err != nil || v < 2 {
1753 return false, nil
1754 } else if v > 2 {
1755 return true, nil
1756 }
1757 if v, err := strconv.Atoi(subvers[2]); err != nil || v < 2 {
1758 return false, nil
1759 }
1760 return true, nil
1761 }
1762
View as plain text