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