1
2
3
4
5
6
7
8 package dwarf
9
10 import (
11 "bytes"
12 "errors"
13 "fmt"
14 "internal/buildcfg"
15 exec "internal/execabs"
16 "sort"
17 "strconv"
18 "strings"
19
20 "cmd/internal/objabi"
21 )
22
23
24 const InfoPrefix = "go.info."
25
26
27
28 const ConstInfoPrefix = "go.constinfo."
29
30
31
32 const CUInfoPrefix = "go.cuinfo."
33
34
35
36 const AbstractFuncSuffix = "$abstract"
37
38
39
40 var logDwarf bool
41
42
43 type Sym interface {
44 Length(dwarfContext interface{}) int64
45 }
46
47
48 type Var struct {
49 Name string
50 Abbrev int
51 IsReturnValue bool
52 IsInlFormal bool
53 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 }
66
67
68
69
70
71
72
73 type Scope struct {
74 Parent int32
75 Ranges []Range
76 Vars []*Var
77 }
78
79
80 type Range struct {
81 Start, End int64
82 }
83
84
85
86 type FnState struct {
87 Name string
88 Importpath string
89 Info Sym
90 Filesym Sym
91 Loc Sym
92 Ranges Sym
93 Absfn Sym
94 StartPC Sym
95 Size int64
96 External bool
97 Scopes []Scope
98 InlCalls InlCalls
99 UseBASEntries bool
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 CallFile Sym
170
171
172 CallLine uint32
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 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 AddFileRef(s Sym, f interface{})
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
319 DW_AT_internal_location = 253
320 )
321
322
323 const (
324 DW_ABRV_NULL = iota
325 DW_ABRV_COMPUNIT
326 DW_ABRV_COMPUNIT_TEXTLESS
327 DW_ABRV_FUNCTION
328 DW_ABRV_FUNCTION_ABSTRACT
329 DW_ABRV_FUNCTION_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_NABRV
364 )
365
366 type dwAbbrev struct {
367 tag uint8
368 children uint8
369 attr []dwAttrForm
370 }
371
372 var abbrevsFinalized bool
373
374
375
376
377
378
379
380 func expandPseudoForm(form uint8) uint8 {
381
382 if form != DW_FORM_udata_pseudo {
383 return form
384 }
385 expandedForm := DW_FORM_udata
386 if buildcfg.GOOS == "darwin" || buildcfg.GOOS == "ios" {
387 expandedForm = DW_FORM_data4
388 }
389 return uint8(expandedForm)
390 }
391
392
393
394 func Abbrevs() []dwAbbrev {
395 if abbrevsFinalized {
396 return abbrevs[:]
397 }
398 for i := 1; i < DW_NABRV; i++ {
399 for j := 0; j < len(abbrevs[i].attr); j++ {
400 abbrevs[i].attr[j].form = expandPseudoForm(abbrevs[i].attr[j].form)
401 }
402 }
403 abbrevsFinalized = true
404 return abbrevs[:]
405 }
406
407
408
409
410
411 var abbrevs = [DW_NABRV]dwAbbrev{
412
413 {0, 0, []dwAttrForm{}},
414
415
416 {
417 DW_TAG_compile_unit,
418 DW_CHILDREN_yes,
419 []dwAttrForm{
420 {DW_AT_name, DW_FORM_string},
421 {DW_AT_language, DW_FORM_data1},
422 {DW_AT_stmt_list, DW_FORM_sec_offset},
423 {DW_AT_low_pc, DW_FORM_addr},
424 {DW_AT_ranges, DW_FORM_sec_offset},
425 {DW_AT_comp_dir, DW_FORM_string},
426 {DW_AT_producer, DW_FORM_string},
427 {DW_AT_go_package_name, DW_FORM_string},
428 },
429 },
430
431
432 {
433 DW_TAG_compile_unit,
434 DW_CHILDREN_yes,
435 []dwAttrForm{
436 {DW_AT_name, DW_FORM_string},
437 {DW_AT_language, DW_FORM_data1},
438 {DW_AT_comp_dir, DW_FORM_string},
439 {DW_AT_producer, DW_FORM_string},
440 {DW_AT_go_package_name, DW_FORM_string},
441 },
442 },
443
444
445 {
446 DW_TAG_subprogram,
447 DW_CHILDREN_yes,
448 []dwAttrForm{
449 {DW_AT_name, DW_FORM_string},
450 {DW_AT_low_pc, DW_FORM_addr},
451 {DW_AT_high_pc, DW_FORM_addr},
452 {DW_AT_frame_base, DW_FORM_block1},
453 {DW_AT_decl_file, DW_FORM_data4},
454 {DW_AT_external, DW_FORM_flag},
455 },
456 },
457
458
459 {
460 DW_TAG_subprogram,
461 DW_CHILDREN_yes,
462 []dwAttrForm{
463 {DW_AT_name, DW_FORM_string},
464 {DW_AT_inline, DW_FORM_data1},
465 {DW_AT_external, DW_FORM_flag},
466 },
467 },
468
469
470 {
471 DW_TAG_subprogram,
472 DW_CHILDREN_yes,
473 []dwAttrForm{
474 {DW_AT_abstract_origin, DW_FORM_ref_addr},
475 {DW_AT_low_pc, DW_FORM_addr},
476 {DW_AT_high_pc, DW_FORM_addr},
477 {DW_AT_frame_base, DW_FORM_block1},
478 },
479 },
480
481
482 {
483 DW_TAG_inlined_subroutine,
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_call_file, DW_FORM_data4},
490 {DW_AT_call_line, DW_FORM_udata_pseudo},
491 },
492 },
493
494
495 {
496 DW_TAG_inlined_subroutine,
497 DW_CHILDREN_yes,
498 []dwAttrForm{
499 {DW_AT_abstract_origin, DW_FORM_ref_addr},
500 {DW_AT_ranges, DW_FORM_sec_offset},
501 {DW_AT_call_file, DW_FORM_data4},
502 {DW_AT_call_line, DW_FORM_udata_pseudo},
503 },
504 },
505
506
507 {
508 DW_TAG_variable,
509 DW_CHILDREN_no,
510 []dwAttrForm{
511 {DW_AT_name, DW_FORM_string},
512 {DW_AT_location, DW_FORM_block1},
513 {DW_AT_type, DW_FORM_ref_addr},
514 {DW_AT_external, DW_FORM_flag},
515 },
516 },
517
518
519 {
520 DW_TAG_constant,
521 DW_CHILDREN_no,
522 []dwAttrForm{
523 {DW_AT_name, DW_FORM_string},
524 {DW_AT_type, DW_FORM_ref_addr},
525 {DW_AT_const_value, DW_FORM_sdata},
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_decl_line, DW_FORM_udata},
536 {DW_AT_type, DW_FORM_ref_addr},
537 {DW_AT_location, DW_FORM_block1},
538 },
539 },
540
541
542 {
543 DW_TAG_variable,
544 DW_CHILDREN_no,
545 []dwAttrForm{
546 {DW_AT_name, DW_FORM_string},
547 {DW_AT_decl_line, DW_FORM_udata},
548 {DW_AT_type, DW_FORM_ref_addr},
549 {DW_AT_location, DW_FORM_sec_offset},
550 },
551 },
552
553
554 {
555 DW_TAG_variable,
556 DW_CHILDREN_no,
557 []dwAttrForm{
558 {DW_AT_name, DW_FORM_string},
559 {DW_AT_decl_line, DW_FORM_udata},
560 {DW_AT_type, DW_FORM_ref_addr},
561 },
562 },
563
564
565 {
566 DW_TAG_variable,
567 DW_CHILDREN_no,
568 []dwAttrForm{
569 {DW_AT_abstract_origin, DW_FORM_ref_addr},
570 {DW_AT_location, DW_FORM_block1},
571 },
572 },
573
574
575 {
576 DW_TAG_variable,
577 DW_CHILDREN_no,
578 []dwAttrForm{
579 {DW_AT_abstract_origin, DW_FORM_ref_addr},
580 {DW_AT_location, DW_FORM_sec_offset},
581 },
582 },
583
584
585 {
586 DW_TAG_formal_parameter,
587 DW_CHILDREN_no,
588 []dwAttrForm{
589 {DW_AT_name, DW_FORM_string},
590 {DW_AT_variable_parameter, DW_FORM_flag},
591 {DW_AT_decl_line, DW_FORM_udata},
592 {DW_AT_type, DW_FORM_ref_addr},
593 {DW_AT_location, DW_FORM_block1},
594 },
595 },
596
597
598 {
599 DW_TAG_formal_parameter,
600 DW_CHILDREN_no,
601 []dwAttrForm{
602 {DW_AT_name, DW_FORM_string},
603 {DW_AT_variable_parameter, DW_FORM_flag},
604 {DW_AT_decl_line, DW_FORM_udata},
605 {DW_AT_type, DW_FORM_ref_addr},
606 {DW_AT_location, DW_FORM_sec_offset},
607 },
608 },
609
610
611 {
612 DW_TAG_formal_parameter,
613 DW_CHILDREN_no,
614 []dwAttrForm{
615 {DW_AT_name, DW_FORM_string},
616 {DW_AT_variable_parameter, DW_FORM_flag},
617 {DW_AT_type, DW_FORM_ref_addr},
618 },
619 },
620
621
622 {
623 DW_TAG_formal_parameter,
624 DW_CHILDREN_no,
625 []dwAttrForm{
626 {DW_AT_abstract_origin, DW_FORM_ref_addr},
627 {DW_AT_location, DW_FORM_block1},
628 },
629 },
630
631
632 {
633 DW_TAG_formal_parameter,
634 DW_CHILDREN_no,
635 []dwAttrForm{
636 {DW_AT_abstract_origin, DW_FORM_ref_addr},
637 {DW_AT_location, DW_FORM_sec_offset},
638 },
639 },
640
641
642 {
643 DW_TAG_lexical_block,
644 DW_CHILDREN_yes,
645 []dwAttrForm{
646 {DW_AT_ranges, DW_FORM_sec_offset},
647 },
648 },
649
650
651 {
652 DW_TAG_lexical_block,
653 DW_CHILDREN_yes,
654 []dwAttrForm{
655 {DW_AT_low_pc, DW_FORM_addr},
656 {DW_AT_high_pc, DW_FORM_addr},
657 },
658 },
659
660
661 {
662 DW_TAG_member,
663 DW_CHILDREN_no,
664 []dwAttrForm{
665 {DW_AT_name, DW_FORM_string},
666 {DW_AT_data_member_location, DW_FORM_udata},
667 {DW_AT_type, DW_FORM_ref_addr},
668 {DW_AT_go_embedded_field, DW_FORM_flag},
669 },
670 },
671
672
673 {
674 DW_TAG_formal_parameter,
675 DW_CHILDREN_no,
676
677
678 []dwAttrForm{
679 {DW_AT_type, DW_FORM_ref_addr},
680 },
681 },
682
683
684 {
685 DW_TAG_unspecified_parameters,
686 DW_CHILDREN_no,
687 []dwAttrForm{},
688 },
689
690
691 {
692 DW_TAG_subrange_type,
693 DW_CHILDREN_no,
694
695
696 []dwAttrForm{
697 {DW_AT_type, DW_FORM_ref_addr},
698 {DW_AT_count, DW_FORM_udata},
699 },
700 },
701
702
703
704 {
705 DW_TAG_unspecified_type,
706 DW_CHILDREN_no,
707 []dwAttrForm{
708 {DW_AT_name, DW_FORM_string},
709 },
710 },
711
712
713 {
714 DW_TAG_base_type,
715 DW_CHILDREN_no,
716 []dwAttrForm{
717 {DW_AT_name, DW_FORM_string},
718 {DW_AT_encoding, DW_FORM_data1},
719 {DW_AT_byte_size, DW_FORM_data1},
720 {DW_AT_go_kind, DW_FORM_data1},
721 {DW_AT_go_runtime_type, DW_FORM_addr},
722 },
723 },
724
725
726
727 {
728 DW_TAG_array_type,
729 DW_CHILDREN_yes,
730 []dwAttrForm{
731 {DW_AT_name, DW_FORM_string},
732 {DW_AT_type, DW_FORM_ref_addr},
733 {DW_AT_byte_size, DW_FORM_udata},
734 {DW_AT_go_kind, DW_FORM_data1},
735 {DW_AT_go_runtime_type, DW_FORM_addr},
736 },
737 },
738
739
740 {
741 DW_TAG_typedef,
742 DW_CHILDREN_no,
743 []dwAttrForm{
744 {DW_AT_name, DW_FORM_string},
745 {DW_AT_type, DW_FORM_ref_addr},
746 {DW_AT_go_kind, DW_FORM_data1},
747 {DW_AT_go_runtime_type, DW_FORM_addr},
748 {DW_AT_go_elem, DW_FORM_ref_addr},
749 },
750 },
751
752
753 {
754 DW_TAG_subroutine_type,
755 DW_CHILDREN_yes,
756 []dwAttrForm{
757 {DW_AT_name, DW_FORM_string},
758 {DW_AT_byte_size, DW_FORM_udata},
759 {DW_AT_go_kind, DW_FORM_data1},
760 {DW_AT_go_runtime_type, DW_FORM_addr},
761 },
762 },
763
764
765 {
766 DW_TAG_typedef,
767 DW_CHILDREN_yes,
768 []dwAttrForm{
769 {DW_AT_name, DW_FORM_string},
770 {DW_AT_type, DW_FORM_ref_addr},
771 {DW_AT_go_kind, DW_FORM_data1},
772 {DW_AT_go_runtime_type, DW_FORM_addr},
773 },
774 },
775
776
777 {
778 DW_TAG_typedef,
779 DW_CHILDREN_no,
780 []dwAttrForm{
781 {DW_AT_name, DW_FORM_string},
782 {DW_AT_type, DW_FORM_ref_addr},
783 {DW_AT_go_kind, DW_FORM_data1},
784 {DW_AT_go_runtime_type, DW_FORM_addr},
785 {DW_AT_go_key, DW_FORM_ref_addr},
786 {DW_AT_go_elem, DW_FORM_ref_addr},
787 },
788 },
789
790
791 {
792 DW_TAG_pointer_type,
793 DW_CHILDREN_no,
794 []dwAttrForm{
795 {DW_AT_name, DW_FORM_string},
796 {DW_AT_type, DW_FORM_ref_addr},
797 {DW_AT_go_kind, DW_FORM_data1},
798 {DW_AT_go_runtime_type, DW_FORM_addr},
799 },
800 },
801
802
803 {
804 DW_TAG_pointer_type,
805 DW_CHILDREN_no,
806 []dwAttrForm{
807 {DW_AT_name, DW_FORM_string},
808 },
809 },
810
811
812 {
813 DW_TAG_structure_type,
814 DW_CHILDREN_yes,
815 []dwAttrForm{
816 {DW_AT_name, DW_FORM_string},
817 {DW_AT_byte_size, DW_FORM_udata},
818 {DW_AT_go_kind, DW_FORM_data1},
819 {DW_AT_go_runtime_type, DW_FORM_addr},
820 {DW_AT_go_elem, DW_FORM_ref_addr},
821 },
822 },
823
824
825 {
826 DW_TAG_structure_type,
827 DW_CHILDREN_yes,
828 []dwAttrForm{
829 {DW_AT_name, DW_FORM_string},
830 {DW_AT_byte_size, DW_FORM_udata},
831 {DW_AT_go_kind, DW_FORM_data1},
832 {DW_AT_go_runtime_type, DW_FORM_addr},
833 },
834 },
835
836
837 {
838 DW_TAG_structure_type,
839 DW_CHILDREN_yes,
840 []dwAttrForm{
841 {DW_AT_name, DW_FORM_string},
842 {DW_AT_byte_size, DW_FORM_udata},
843 {DW_AT_go_kind, DW_FORM_data1},
844 {DW_AT_go_runtime_type, DW_FORM_addr},
845 },
846 },
847
848
849 {
850 DW_TAG_typedef,
851 DW_CHILDREN_no,
852 []dwAttrForm{
853 {DW_AT_name, DW_FORM_string},
854 {DW_AT_type, DW_FORM_ref_addr},
855 },
856 },
857 }
858
859
860 func GetAbbrev() []byte {
861 abbrevs := Abbrevs()
862 var buf []byte
863 for i := 1; i < DW_NABRV; i++ {
864
865 buf = AppendUleb128(buf, uint64(i))
866 buf = AppendUleb128(buf, uint64(abbrevs[i].tag))
867 buf = append(buf, abbrevs[i].children)
868 for _, f := range abbrevs[i].attr {
869 buf = AppendUleb128(buf, uint64(f.attr))
870 buf = AppendUleb128(buf, uint64(f.form))
871 }
872 buf = append(buf, 0, 0)
873 }
874 return append(buf, 0)
875 }
876
877
880
881
882
883
884
885
886
887 type DWAttr struct {
888 Link *DWAttr
889 Atr uint16
890 Cls uint8
891 Value int64
892 Data interface{}
893 }
894
895
896 type DWDie struct {
897 Abbrev int
898 Link *DWDie
899 Child *DWDie
900 Attr *DWAttr
901 Sym Sym
902 }
903
904 func putattr(ctxt Context, s Sym, abbrev int, form int, cls int, value int64, data interface{}) error {
905 switch form {
906 case DW_FORM_addr:
907
908 if data == nil && value == 0 {
909 ctxt.AddInt(s, ctxt.PtrSize(), 0)
910 break
911 }
912 if cls == DW_CLS_GO_TYPEREF {
913 ctxt.AddSectionOffset(s, ctxt.PtrSize(), data, value)
914 break
915 }
916 ctxt.AddAddress(s, data, value)
917
918 case DW_FORM_block1:
919 if cls == DW_CLS_ADDRESS {
920 ctxt.AddInt(s, 1, int64(1+ctxt.PtrSize()))
921 ctxt.AddInt(s, 1, DW_OP_addr)
922 ctxt.AddAddress(s, data, 0)
923 break
924 }
925
926 value &= 0xff
927 ctxt.AddInt(s, 1, value)
928 p := data.([]byte)[:value]
929 ctxt.AddBytes(s, p)
930
931 case DW_FORM_block2:
932 value &= 0xffff
933
934 ctxt.AddInt(s, 2, value)
935 p := data.([]byte)[:value]
936 ctxt.AddBytes(s, p)
937
938 case DW_FORM_block4:
939 value &= 0xffffffff
940
941 ctxt.AddInt(s, 4, value)
942 p := data.([]byte)[:value]
943 ctxt.AddBytes(s, p)
944
945 case DW_FORM_block:
946 Uleb128put(ctxt, s, value)
947
948 p := data.([]byte)[:value]
949 ctxt.AddBytes(s, p)
950
951 case DW_FORM_data1:
952 ctxt.AddInt(s, 1, value)
953
954 case DW_FORM_data2:
955 ctxt.AddInt(s, 2, value)
956
957 case DW_FORM_data4:
958 if cls == DW_CLS_PTR {
959 ctxt.AddDWARFAddrSectionOffset(s, data, value)
960 break
961 }
962 ctxt.AddInt(s, 4, value)
963
964 case DW_FORM_data8:
965 ctxt.AddInt(s, 8, value)
966
967 case DW_FORM_sdata:
968 Sleb128put(ctxt, s, value)
969
970 case DW_FORM_udata:
971 Uleb128put(ctxt, s, value)
972
973 case DW_FORM_string:
974 str := data.(string)
975 ctxt.AddString(s, str)
976
977 for i := int64(len(str)); i < value; i++ {
978 ctxt.AddInt(s, 1, 0)
979 }
980
981 case DW_FORM_flag:
982 if value != 0 {
983 ctxt.AddInt(s, 1, 1)
984 } else {
985 ctxt.AddInt(s, 1, 0)
986 }
987
988
989
990 case DW_FORM_ref_addr:
991 fallthrough
992 case DW_FORM_sec_offset:
993 if data == nil {
994 return fmt.Errorf("dwarf: null reference in %d", abbrev)
995 }
996 ctxt.AddDWARFAddrSectionOffset(s, data, value)
997
998 case DW_FORM_ref1,
999 DW_FORM_ref2,
1000 DW_FORM_ref4,
1001 DW_FORM_ref8,
1002 DW_FORM_ref_udata,
1003
1004 DW_FORM_strp,
1005 DW_FORM_indirect:
1006 fallthrough
1007 default:
1008 return fmt.Errorf("dwarf: unsupported attribute form %d / class %d", form, cls)
1009 }
1010 return nil
1011 }
1012
1013
1014
1015
1016
1017 func PutAttrs(ctxt Context, s Sym, abbrev int, attr *DWAttr) {
1018 abbrevs := Abbrevs()
1019 Outer:
1020 for _, f := range abbrevs[abbrev].attr {
1021 for ap := attr; ap != nil; ap = ap.Link {
1022 if ap.Atr == f.attr {
1023 putattr(ctxt, s, abbrev, int(f.form), int(ap.Cls), ap.Value, ap.Data)
1024 continue Outer
1025 }
1026 }
1027
1028 putattr(ctxt, s, abbrev, int(f.form), 0, 0, nil)
1029 }
1030 }
1031
1032
1033 func HasChildren(die *DWDie) bool {
1034 abbrevs := Abbrevs()
1035 return abbrevs[die.Abbrev].children != 0
1036 }
1037
1038
1039 func PutIntConst(ctxt Context, info, typ Sym, name string, val int64) {
1040 Uleb128put(ctxt, info, DW_ABRV_INT_CONSTANT)
1041 putattr(ctxt, info, DW_ABRV_INT_CONSTANT, DW_FORM_string, DW_CLS_STRING, int64(len(name)), name)
1042 putattr(ctxt, info, DW_ABRV_INT_CONSTANT, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, typ)
1043 putattr(ctxt, info, DW_ABRV_INT_CONSTANT, DW_FORM_sdata, DW_CLS_CONSTANT, val, nil)
1044 }
1045
1046
1047 func PutGlobal(ctxt Context, info, typ, gvar Sym, name string) {
1048 Uleb128put(ctxt, info, DW_ABRV_VARIABLE)
1049 putattr(ctxt, info, DW_ABRV_VARIABLE, DW_FORM_string, DW_CLS_STRING, int64(len(name)), name)
1050 putattr(ctxt, info, DW_ABRV_VARIABLE, DW_FORM_block1, DW_CLS_ADDRESS, 0, gvar)
1051 putattr(ctxt, info, DW_ABRV_VARIABLE, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, typ)
1052 putattr(ctxt, info, DW_ABRV_VARIABLE, DW_FORM_flag, DW_CLS_FLAG, 1, nil)
1053 }
1054
1055
1056
1057
1058 func PutBasedRanges(ctxt Context, sym Sym, ranges []Range) {
1059 ps := ctxt.PtrSize()
1060
1061 for _, r := range ranges {
1062 ctxt.AddInt(sym, ps, r.Start)
1063 ctxt.AddInt(sym, ps, r.End)
1064 }
1065
1066 ctxt.AddInt(sym, ps, 0)
1067 ctxt.AddInt(sym, ps, 0)
1068 }
1069
1070
1071
1072 func (s *FnState) PutRanges(ctxt Context, ranges []Range) {
1073 ps := ctxt.PtrSize()
1074 sym, base := s.Ranges, s.StartPC
1075
1076 if s.UseBASEntries {
1077
1078
1079 ctxt.AddInt(sym, ps, -1)
1080 ctxt.AddAddress(sym, base, 0)
1081 PutBasedRanges(ctxt, sym, ranges)
1082 return
1083 }
1084
1085
1086 for _, r := range ranges {
1087 ctxt.AddCURelativeAddress(sym, base, r.Start)
1088 ctxt.AddCURelativeAddress(sym, base, r.End)
1089 }
1090
1091 ctxt.AddInt(sym, ps, 0)
1092 ctxt.AddInt(sym, ps, 0)
1093 }
1094
1095
1096
1097
1098 func isEmptyInlinedCall(slot int, calls *InlCalls) bool {
1099 ic := &calls.Calls[slot]
1100 if ic.InlIndex == -2 {
1101 return true
1102 }
1103 live := false
1104 for _, k := range ic.Children {
1105 if !isEmptyInlinedCall(k, calls) {
1106 live = true
1107 }
1108 }
1109 if len(ic.Ranges) > 0 {
1110 live = true
1111 }
1112 if !live {
1113 ic.InlIndex = -2
1114 }
1115 return !live
1116 }
1117
1118
1119
1120 func inlChildren(slot int, calls *InlCalls) []int {
1121 var kids []int
1122 if slot != -1 {
1123 for _, k := range calls.Calls[slot].Children {
1124 if !isEmptyInlinedCall(k, calls) {
1125 kids = append(kids, k)
1126 }
1127 }
1128 } else {
1129 for k := 0; k < len(calls.Calls); k += 1 {
1130 if calls.Calls[k].Root && !isEmptyInlinedCall(k, calls) {
1131 kids = append(kids, k)
1132 }
1133 }
1134 }
1135 return kids
1136 }
1137
1138 func inlinedVarTable(inlcalls *InlCalls) map[*Var]bool {
1139 vars := make(map[*Var]bool)
1140 for _, ic := range inlcalls.Calls {
1141 for _, v := range ic.InlVars {
1142 vars[v] = true
1143 }
1144 }
1145 return vars
1146 }
1147
1148
1149
1150
1151
1152
1153
1154 func putPrunedScopes(ctxt Context, s *FnState, fnabbrev int) error {
1155 if len(s.Scopes) == 0 {
1156 return nil
1157 }
1158 scopes := make([]Scope, len(s.Scopes), len(s.Scopes))
1159 pvars := inlinedVarTable(&s.InlCalls)
1160 for k, s := range s.Scopes {
1161 var pruned Scope = Scope{Parent: s.Parent, Ranges: s.Ranges}
1162 for i := 0; i < len(s.Vars); i++ {
1163 _, found := pvars[s.Vars[i]]
1164 if !found {
1165 pruned.Vars = append(pruned.Vars, s.Vars[i])
1166 }
1167 }
1168 sort.Sort(byChildIndex(pruned.Vars))
1169 scopes[k] = pruned
1170 }
1171 var encbuf [20]byte
1172 if putscope(ctxt, s, scopes, 0, fnabbrev, encbuf[:0]) < int32(len(scopes)) {
1173 return errors.New("multiple toplevel scopes")
1174 }
1175 return nil
1176 }
1177
1178
1179
1180
1181
1182
1183
1184
1185 func PutAbstractFunc(ctxt Context, s *FnState) error {
1186
1187 if logDwarf {
1188 ctxt.Logf("PutAbstractFunc(%v)\n", s.Absfn)
1189 }
1190
1191 abbrev := DW_ABRV_FUNCTION_ABSTRACT
1192 Uleb128put(ctxt, s.Absfn, int64(abbrev))
1193
1194 fullname := s.Name
1195 if strings.HasPrefix(s.Name, "\"\".") {
1196
1197
1198
1199
1200
1201
1202
1203 fullname = objabi.PathToPrefix(s.Importpath) + "." + s.Name[3:]
1204 }
1205 putattr(ctxt, s.Absfn, abbrev, DW_FORM_string, DW_CLS_STRING, int64(len(fullname)), fullname)
1206
1207
1208 putattr(ctxt, s.Absfn, abbrev, DW_FORM_data1, DW_CLS_CONSTANT, int64(DW_INL_inlined), nil)
1209
1210 var ev int64
1211 if s.External {
1212 ev = 1
1213 }
1214 putattr(ctxt, s.Absfn, abbrev, DW_FORM_flag, DW_CLS_FLAG, ev, 0)
1215
1216
1217 var flattened []*Var
1218
1219
1220
1221 var offsets []int32
1222
1223
1224 if len(s.Scopes) > 0 {
1225
1226
1227
1228 pvars := inlinedVarTable(&s.InlCalls)
1229 for _, scope := range s.Scopes {
1230 for i := 0; i < len(scope.Vars); i++ {
1231 _, found := pvars[scope.Vars[i]]
1232 if found || !scope.Vars[i].IsInAbstract {
1233 continue
1234 }
1235 flattened = append(flattened, scope.Vars[i])
1236 }
1237 }
1238 if len(flattened) > 0 {
1239 sort.Sort(byChildIndex(flattened))
1240
1241 if logDwarf {
1242 ctxt.Logf("putAbstractScope(%v): vars:", s.Info)
1243 for i, v := range flattened {
1244 ctxt.Logf(" %d:%s", i, v.Name)
1245 }
1246 ctxt.Logf("\n")
1247 }
1248
1249
1250
1251
1252 for _, v := range flattened {
1253 offsets = append(offsets, int32(ctxt.CurrentOffset(s.Absfn)))
1254 putAbstractVar(ctxt, s.Absfn, v)
1255 }
1256 }
1257 }
1258 ctxt.RecordChildDieOffsets(s.Absfn, flattened, offsets)
1259
1260 Uleb128put(ctxt, s.Absfn, 0)
1261 return nil
1262 }
1263
1264
1265
1266
1267
1268
1269 func putInlinedFunc(ctxt Context, s *FnState, callersym Sym, callIdx int) error {
1270 ic := s.InlCalls.Calls[callIdx]
1271 callee := ic.AbsFunSym
1272
1273 abbrev := DW_ABRV_INLINED_SUBROUTINE_RANGES
1274 if len(ic.Ranges) == 1 {
1275 abbrev = DW_ABRV_INLINED_SUBROUTINE
1276 }
1277 Uleb128put(ctxt, s.Info, int64(abbrev))
1278
1279 if logDwarf {
1280 ctxt.Logf("putInlinedFunc(caller=%v,callee=%v,abbrev=%d)\n", callersym, callee, abbrev)
1281 }
1282
1283
1284 putattr(ctxt, s.Info, abbrev, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, callee)
1285
1286 if abbrev == DW_ABRV_INLINED_SUBROUTINE_RANGES {
1287 putattr(ctxt, s.Info, abbrev, DW_FORM_sec_offset, DW_CLS_PTR, s.Ranges.Length(ctxt), s.Ranges)
1288 s.PutRanges(ctxt, ic.Ranges)
1289 } else {
1290 st := ic.Ranges[0].Start
1291 en := ic.Ranges[0].End
1292 putattr(ctxt, s.Info, abbrev, DW_FORM_addr, DW_CLS_ADDRESS, st, s.StartPC)
1293 putattr(ctxt, s.Info, abbrev, DW_FORM_addr, DW_CLS_ADDRESS, en, s.StartPC)
1294 }
1295
1296
1297 ctxt.AddFileRef(s.Info, ic.CallFile)
1298 form := int(expandPseudoForm(DW_FORM_udata_pseudo))
1299 putattr(ctxt, s.Info, abbrev, form, DW_CLS_CONSTANT, int64(ic.CallLine), nil)
1300
1301
1302 vars := ic.InlVars
1303 sort.Sort(byChildIndex(vars))
1304 inlIndex := ic.InlIndex
1305 var encbuf [20]byte
1306 for _, v := range vars {
1307 if !v.IsInAbstract {
1308 continue
1309 }
1310 putvar(ctxt, s, v, callee, abbrev, inlIndex, encbuf[:0])
1311 }
1312
1313
1314 for _, sib := range inlChildren(callIdx, &s.InlCalls) {
1315 absfn := s.InlCalls.Calls[sib].AbsFunSym
1316 err := putInlinedFunc(ctxt, s, absfn, sib)
1317 if err != nil {
1318 return err
1319 }
1320 }
1321
1322 Uleb128put(ctxt, s.Info, 0)
1323 return nil
1324 }
1325
1326
1327
1328
1329
1330
1331
1332
1333 func PutConcreteFunc(ctxt Context, s *FnState) error {
1334 if logDwarf {
1335 ctxt.Logf("PutConcreteFunc(%v)\n", s.Info)
1336 }
1337 abbrev := DW_ABRV_FUNCTION_CONCRETE
1338 Uleb128put(ctxt, s.Info, int64(abbrev))
1339
1340
1341 putattr(ctxt, s.Info, abbrev, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, s.Absfn)
1342
1343
1344 putattr(ctxt, s.Info, abbrev, DW_FORM_addr, DW_CLS_ADDRESS, 0, s.StartPC)
1345 putattr(ctxt, s.Info, abbrev, DW_FORM_addr, DW_CLS_ADDRESS, s.Size, s.StartPC)
1346
1347
1348 putattr(ctxt, s.Info, abbrev, DW_FORM_block1, DW_CLS_BLOCK, 1, []byte{DW_OP_call_frame_cfa})
1349
1350
1351 if err := putPrunedScopes(ctxt, s, abbrev); err != nil {
1352 return err
1353 }
1354
1355
1356 for _, sib := range inlChildren(-1, &s.InlCalls) {
1357 absfn := s.InlCalls.Calls[sib].AbsFunSym
1358 err := putInlinedFunc(ctxt, s, absfn, sib)
1359 if err != nil {
1360 return err
1361 }
1362 }
1363
1364 Uleb128put(ctxt, s.Info, 0)
1365 return nil
1366 }
1367
1368
1369
1370
1371
1372
1373 func PutDefaultFunc(ctxt Context, s *FnState) error {
1374 if logDwarf {
1375 ctxt.Logf("PutDefaultFunc(%v)\n", s.Info)
1376 }
1377 abbrev := DW_ABRV_FUNCTION
1378 Uleb128put(ctxt, s.Info, int64(abbrev))
1379
1380
1381 name := s.Name
1382 if s.Importpath != "" {
1383 name = strings.Replace(name, "\"\".", objabi.PathToPrefix(s.Importpath)+".", -1)
1384 }
1385
1386 putattr(ctxt, s.Info, DW_ABRV_FUNCTION, DW_FORM_string, DW_CLS_STRING, int64(len(name)), name)
1387 putattr(ctxt, s.Info, abbrev, DW_FORM_addr, DW_CLS_ADDRESS, 0, s.StartPC)
1388 putattr(ctxt, s.Info, abbrev, DW_FORM_addr, DW_CLS_ADDRESS, s.Size, s.StartPC)
1389 putattr(ctxt, s.Info, abbrev, DW_FORM_block1, DW_CLS_BLOCK, 1, []byte{DW_OP_call_frame_cfa})
1390 ctxt.AddFileRef(s.Info, s.Filesym)
1391
1392 var ev int64
1393 if s.External {
1394 ev = 1
1395 }
1396 putattr(ctxt, s.Info, abbrev, DW_FORM_flag, DW_CLS_FLAG, ev, 0)
1397
1398
1399 if err := putPrunedScopes(ctxt, s, abbrev); err != nil {
1400 return err
1401 }
1402
1403
1404 for _, sib := range inlChildren(-1, &s.InlCalls) {
1405 absfn := s.InlCalls.Calls[sib].AbsFunSym
1406 err := putInlinedFunc(ctxt, s, absfn, sib)
1407 if err != nil {
1408 return err
1409 }
1410 }
1411
1412 Uleb128put(ctxt, s.Info, 0)
1413 return nil
1414 }
1415
1416 func putscope(ctxt Context, s *FnState, scopes []Scope, curscope int32, fnabbrev int, encbuf []byte) int32 {
1417
1418 if logDwarf {
1419 ctxt.Logf("putscope(%v,%d): vars:", s.Info, curscope)
1420 for i, v := range scopes[curscope].Vars {
1421 ctxt.Logf(" %d:%d:%s", i, v.ChildIndex, v.Name)
1422 }
1423 ctxt.Logf("\n")
1424 }
1425
1426 for _, v := range scopes[curscope].Vars {
1427 putvar(ctxt, s, v, s.Absfn, fnabbrev, -1, encbuf)
1428 }
1429 this := curscope
1430 curscope++
1431 for curscope < int32(len(scopes)) {
1432 scope := scopes[curscope]
1433 if scope.Parent != this {
1434 return curscope
1435 }
1436
1437 if len(scopes[curscope].Vars) == 0 {
1438 curscope = putscope(ctxt, s, scopes, curscope, fnabbrev, encbuf)
1439 continue
1440 }
1441
1442 if len(scope.Ranges) == 1 {
1443 Uleb128put(ctxt, s.Info, DW_ABRV_LEXICAL_BLOCK_SIMPLE)
1444 putattr(ctxt, s.Info, DW_ABRV_LEXICAL_BLOCK_SIMPLE, DW_FORM_addr, DW_CLS_ADDRESS, scope.Ranges[0].Start, s.StartPC)
1445 putattr(ctxt, s.Info, DW_ABRV_LEXICAL_BLOCK_SIMPLE, DW_FORM_addr, DW_CLS_ADDRESS, scope.Ranges[0].End, s.StartPC)
1446 } else {
1447 Uleb128put(ctxt, s.Info, DW_ABRV_LEXICAL_BLOCK_RANGES)
1448 putattr(ctxt, s.Info, DW_ABRV_LEXICAL_BLOCK_RANGES, DW_FORM_sec_offset, DW_CLS_PTR, s.Ranges.Length(ctxt), s.Ranges)
1449
1450 s.PutRanges(ctxt, scope.Ranges)
1451 }
1452
1453 curscope = putscope(ctxt, s, scopes, curscope, fnabbrev, encbuf)
1454
1455 Uleb128put(ctxt, s.Info, 0)
1456 }
1457 return curscope
1458 }
1459
1460
1461 func concreteVarAbbrev(varAbbrev int) int {
1462 switch varAbbrev {
1463 case DW_ABRV_AUTO:
1464 return DW_ABRV_AUTO_CONCRETE
1465 case DW_ABRV_PARAM:
1466 return DW_ABRV_PARAM_CONCRETE
1467 case DW_ABRV_AUTO_LOCLIST:
1468 return DW_ABRV_AUTO_CONCRETE_LOCLIST
1469 case DW_ABRV_PARAM_LOCLIST:
1470 return DW_ABRV_PARAM_CONCRETE_LOCLIST
1471 default:
1472 panic("should never happen")
1473 }
1474 }
1475
1476
1477 func determineVarAbbrev(v *Var, fnabbrev int) (int, bool, bool) {
1478 abbrev := v.Abbrev
1479
1480
1481
1482 missing := false
1483 switch {
1484 case abbrev == DW_ABRV_AUTO_LOCLIST && v.PutLocationList == nil:
1485 missing = true
1486 abbrev = DW_ABRV_AUTO
1487 case abbrev == DW_ABRV_PARAM_LOCLIST && v.PutLocationList == nil:
1488 missing = true
1489 abbrev = DW_ABRV_PARAM
1490 }
1491
1492
1493 concrete := true
1494 switch fnabbrev {
1495 case DW_ABRV_FUNCTION:
1496 concrete = false
1497 break
1498 case DW_ABRV_FUNCTION_CONCRETE:
1499
1500
1501
1502 if !v.IsInAbstract {
1503 concrete = false
1504 }
1505 case DW_ABRV_INLINED_SUBROUTINE, DW_ABRV_INLINED_SUBROUTINE_RANGES:
1506 default:
1507 panic("should never happen")
1508 }
1509
1510
1511 if concrete {
1512 abbrev = concreteVarAbbrev(abbrev)
1513 }
1514
1515 return abbrev, missing, concrete
1516 }
1517
1518 func abbrevUsesLoclist(abbrev int) bool {
1519 switch abbrev {
1520 case DW_ABRV_AUTO_LOCLIST, DW_ABRV_AUTO_CONCRETE_LOCLIST,
1521 DW_ABRV_PARAM_LOCLIST, DW_ABRV_PARAM_CONCRETE_LOCLIST:
1522 return true
1523 default:
1524 return false
1525 }
1526 }
1527
1528
1529 func putAbstractVar(ctxt Context, info Sym, v *Var) {
1530
1531 abbrev := v.Abbrev
1532 switch abbrev {
1533 case DW_ABRV_AUTO, DW_ABRV_AUTO_LOCLIST:
1534 abbrev = DW_ABRV_AUTO_ABSTRACT
1535 case DW_ABRV_PARAM, DW_ABRV_PARAM_LOCLIST:
1536 abbrev = DW_ABRV_PARAM_ABSTRACT
1537 }
1538
1539 Uleb128put(ctxt, info, int64(abbrev))
1540 putattr(ctxt, info, abbrev, DW_FORM_string, DW_CLS_STRING, int64(len(v.Name)), v.Name)
1541
1542
1543 if abbrev == DW_ABRV_PARAM_ABSTRACT {
1544 var isReturn int64
1545 if v.IsReturnValue {
1546 isReturn = 1
1547 }
1548 putattr(ctxt, info, abbrev, DW_FORM_flag, DW_CLS_FLAG, isReturn, nil)
1549 }
1550
1551
1552 if abbrev != DW_ABRV_PARAM_ABSTRACT {
1553
1554 putattr(ctxt, info, abbrev, DW_FORM_udata, DW_CLS_CONSTANT, int64(v.DeclLine), nil)
1555 }
1556
1557
1558 putattr(ctxt, info, abbrev, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, v.Type)
1559
1560
1561 }
1562
1563 func putvar(ctxt Context, s *FnState, v *Var, absfn Sym, fnabbrev, inlIndex int, encbuf []byte) {
1564
1565 abbrev, missing, concrete := determineVarAbbrev(v, fnabbrev)
1566
1567 Uleb128put(ctxt, s.Info, int64(abbrev))
1568
1569
1570 if concrete {
1571
1572
1573
1574
1575 putattr(ctxt, s.Info, abbrev, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, absfn)
1576 ctxt.RecordDclReference(s.Info, absfn, int(v.ChildIndex), inlIndex)
1577 } else {
1578
1579 n := v.Name
1580 putattr(ctxt, s.Info, abbrev, DW_FORM_string, DW_CLS_STRING, int64(len(n)), n)
1581 if abbrev == DW_ABRV_PARAM || abbrev == DW_ABRV_PARAM_LOCLIST || abbrev == DW_ABRV_PARAM_ABSTRACT {
1582 var isReturn int64
1583 if v.IsReturnValue {
1584 isReturn = 1
1585 }
1586 putattr(ctxt, s.Info, abbrev, DW_FORM_flag, DW_CLS_FLAG, isReturn, nil)
1587 }
1588 putattr(ctxt, s.Info, abbrev, DW_FORM_udata, DW_CLS_CONSTANT, int64(v.DeclLine), nil)
1589 putattr(ctxt, s.Info, abbrev, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, v.Type)
1590 }
1591
1592 if abbrevUsesLoclist(abbrev) {
1593 putattr(ctxt, s.Info, abbrev, DW_FORM_sec_offset, DW_CLS_PTR, s.Loc.Length(ctxt), s.Loc)
1594 v.PutLocationList(s.Loc, s.StartPC)
1595 } else {
1596 loc := encbuf[:0]
1597 switch {
1598 case missing:
1599 break
1600 case v.StackOffset == 0:
1601 loc = append(loc, DW_OP_call_frame_cfa)
1602 default:
1603 loc = append(loc, DW_OP_fbreg)
1604 loc = AppendSleb128(loc, int64(v.StackOffset))
1605 }
1606 putattr(ctxt, s.Info, abbrev, DW_FORM_block1, DW_CLS_BLOCK, int64(len(loc)), loc)
1607 }
1608
1609
1610 }
1611
1612
1613 type byChildIndex []*Var
1614
1615 func (s byChildIndex) Len() int { return len(s) }
1616 func (s byChildIndex) Less(i, j int) bool { return s[i].ChildIndex < s[j].ChildIndex }
1617 func (s byChildIndex) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
1618
1619
1620
1621
1622
1623 func IsDWARFEnabledOnAIXLd(extld string) (bool, error) {
1624 out, err := exec.Command(extld, "-Wl,-V").CombinedOutput()
1625 if err != nil {
1626
1627
1628
1629 if !bytes.Contains(out, []byte("0711-317")) {
1630 return false, fmt.Errorf("%s -Wl,-V failed: %v\n%s", extld, err, out)
1631 }
1632 }
1633
1634
1635
1636 out = bytes.TrimPrefix(out, []byte("/usr/bin/ld: LD "))
1637 vers := string(bytes.Split(out, []byte("("))[0])
1638 subvers := strings.Split(vers, ".")
1639 if len(subvers) != 3 {
1640 return false, fmt.Errorf("cannot parse %s -Wl,-V (%s): %v\n", extld, out, err)
1641 }
1642 if v, err := strconv.Atoi(subvers[0]); err != nil || v < 7 {
1643 return false, nil
1644 } else if v > 7 {
1645 return true, nil
1646 }
1647 if v, err := strconv.Atoi(subvers[1]); err != nil || v < 2 {
1648 return false, nil
1649 } else if v > 2 {
1650 return true, nil
1651 }
1652 if v, err := strconv.Atoi(subvers[2]); err != nil || v < 2 {
1653 return false, nil
1654 }
1655 return true, nil
1656 }
1657
View as plain text