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