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