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