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