1 // Copyright 2016 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
5 // Package dwarf generates DWARF debugging information.
6 // DWARF generation is split between the compiler and the linker,
7 // this package contains the shared code.
23 // InfoPrefix is the prefix for all the symbols containing DWARF info entries.
24 const InfoPrefix = "go.info."
26 // ConstInfoPrefix is the prefix for all symbols containing DWARF info
27 // entries that contain constants.
28 const ConstInfoPrefix = "go.constinfo."
30 // CUInfoPrefix is the prefix for symbols containing information to
31 // populate the DWARF compilation unit info entries.
32 const CUInfoPrefix = "go.cuinfo."
34 // Used to form the symbol name assigned to the DWARF 'abstract subprogram"
35 // info entry for a function
36 const AbstractFuncSuffix = "$abstract"
38 // Controls logging/debugging for selected aspects of DWARF subprogram
39 // generation (functions, scopes).
42 // Sym represents a symbol.
44 Length(dwarfContext interface{}) int64
47 // A Var represents a local variable or a function parameter.
50 Abbrev int // Either DW_ABRV_AUTO[_LOCLIST] or DW_ABRV_PARAM[_LOCLIST]
53 DictIndex uint16 // index of the dictionary entry describing the type of this variable
55 // This package can't use the ssa package, so it can't mention ssa.FuncDebug,
56 // so indirect through a closure.
57 PutLocationList func(listSym, startPC Sym)
63 InlIndex int32 // subtract 1 to form real index into InlTree
64 ChildIndex int32 // child DIE index in abstract function
65 IsInAbstract bool // variable exists in abstract function
68 // A Scope represents a lexical scope. All variables declared within a
69 // scope will only be visible to instructions covered by the scope.
70 // Lexical scopes are contiguous in source files but can end up being
71 // compiled to discontiguous blocks of instructions in the executable.
72 // The Ranges field lists all the blocks of instructions that belong
80 // A Range represents a half-open interval [Start, End).
85 // This container is used by the PutFunc* variants below when
86 // creating the DWARF subprogram DIE(s) for a function.
102 dictIndexToOffset []int64
105 func EnableLogging(doit bool) {
109 // MergeRanges creates a new range list by merging the ranges from
110 // its two arguments, then returns the new list.
111 func MergeRanges(in1, in2 []Range) []Range {
112 out := make([]Range, 0, len(in1)+len(in2))
116 if i < len(in2) && j < len(in1) {
117 if in2[i].Start < in1[j].Start {
124 } else if i < len(in2) {
127 } else if j < len(in1) {
134 if n := len(out); n > 0 && cur.Start <= out[n-1].End {
135 out[n-1].End = cur.End
137 out = append(out, cur)
144 // UnifyRanges merges the ranges from 'c' into the list of ranges for 's'.
145 func (s *Scope) UnifyRanges(c *Scope) {
146 s.Ranges = MergeRanges(s.Ranges, c.Ranges)
149 // AppendRange adds r to s, if r is non-empty.
150 // If possible, it extends the last Range in s.Ranges; if not, it creates a new one.
151 func (s *Scope) AppendRange(r Range) {
152 if r.End <= r.Start {
156 if i > 0 && s.Ranges[i-1].End == r.Start {
157 s.Ranges[i-1].End = r.End
160 s.Ranges = append(s.Ranges, r)
163 type InlCalls struct {
167 type InlCall struct {
168 // index into ctx.InlTree describing the call inlined here
171 // Symbol of file containing inlined call site (really *obj.LSym).
174 // Line number of inlined call site.
177 // Dwarf abstract subroutine symbol (really *obj.LSym).
180 // Indices of child inlines within Calls array above.
183 // entries in this list are PAUTO's created by the inliner to
184 // capture the promoted formals and locals of the inlined callee.
187 // PC ranges for this inlined call.
190 // Root call (not a child of some other call).
194 // A Context specifies how to add data to a Sym.
195 type Context interface {
197 AddInt(s Sym, size int, i int64)
198 AddBytes(s Sym, b []byte)
199 AddAddress(s Sym, t interface{}, ofs int64)
200 AddCURelativeAddress(s Sym, t interface{}, ofs int64)
201 AddSectionOffset(s Sym, size int, t interface{}, ofs int64)
202 AddDWARFAddrSectionOffset(s Sym, t interface{}, ofs int64)
203 CurrentOffset(s Sym) int64
204 RecordDclReference(from Sym, to Sym, dclIdx int, inlIndex int)
205 RecordChildDieOffsets(s Sym, vars []*Var, offsets []int32)
206 AddString(s Sym, v string)
207 AddFileRef(s Sym, f interface{})
208 Logf(format string, args ...interface{})
211 // AppendUleb128 appends v to b using DWARF's unsigned LEB128 encoding.
212 func AppendUleb128(b []byte, v uint64) []byte {
227 // AppendSleb128 appends v to b using DWARF's signed LEB128 encoding.
228 func AppendSleb128(b []byte, v int64) []byte {
233 if (v != -1 || s == 0) && (v != 0 || s != 0) {
244 // sevenbits contains all unsigned seven bit numbers, indexed by their value.
245 var sevenbits = [...]byte{
246 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
247 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
248 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
249 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
250 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
251 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
252 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
253 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
256 // sevenBitU returns the unsigned LEB128 encoding of v if v is seven bits and nil otherwise.
257 // The contents of the returned slice must not be modified.
258 func sevenBitU(v int64) []byte {
259 if uint64(v) < uint64(len(sevenbits)) {
260 return sevenbits[v : v+1]
265 // sevenBitS returns the signed LEB128 encoding of v if v is seven bits and nil otherwise.
266 // The contents of the returned slice must not be modified.
267 func sevenBitS(v int64) []byte {
269 return sevenbits[v : v+1]
271 if uint64(-v) <= 64 {
272 return sevenbits[128+v : 128+v+1]
277 // Uleb128put appends v to s using DWARF's unsigned LEB128 encoding.
278 func Uleb128put(ctxt Context, s Sym, v int64) {
282 b = AppendUleb128(encbuf[:0], uint64(v))
287 // Sleb128put appends v to s using DWARF's signed LEB128 encoding.
288 func Sleb128put(ctxt Context, s Sym, v int64) {
292 b = AppendSleb128(encbuf[:0], v)
298 * Defining Abbrevs. This is hardcoded on a per-platform basis (that is,
299 * each platform will see a fixed abbrev table for all objects); the number
300 * of abbrev entries is fairly small (compared to C++ objects). The DWARF
301 * spec places no restriction on the ordering of attributes in the
302 * Abbrevs and DIEs, and we will always write them out in the order
303 * of declaration in the abbrev.
305 type dwAttrForm struct {
310 // Go-specific type attributes.
312 DW_AT_go_kind = 0x2900
313 DW_AT_go_key = 0x2901
314 DW_AT_go_elem = 0x2902
315 // Attribute for DW_TAG_member of a struct type.
316 // Nonzero value indicates the struct field is an embedded field.
317 DW_AT_go_embedded_field = 0x2903
318 DW_AT_go_runtime_type = 0x2904
320 DW_AT_go_package_name = 0x2905 // Attribute for DW_TAG_compile_unit
321 DW_AT_go_dict_index = 0x2906 // Attribute for DW_TAG_typedef_type, index of the dictionary entry describing the real type of this type shape
323 DW_AT_internal_location = 253 // params and locals; not emitted
326 // Index into the abbrevs table below.
330 DW_ABRV_COMPUNIT_TEXTLESS
333 DW_ABRV_FUNCTION_ABSTRACT
334 DW_ABRV_FUNCTION_CONCRETE
335 DW_ABRV_WRAPPER_CONCRETE
336 DW_ABRV_INLINED_SUBROUTINE
337 DW_ABRV_INLINED_SUBROUTINE_RANGES
342 DW_ABRV_AUTO_ABSTRACT
343 DW_ABRV_AUTO_CONCRETE
344 DW_ABRV_AUTO_CONCRETE_LOCLIST
346 DW_ABRV_PARAM_LOCLIST
347 DW_ABRV_PARAM_ABSTRACT
348 DW_ABRV_PARAM_CONCRETE
349 DW_ABRV_PARAM_CONCRETE_LOCLIST
350 DW_ABRV_LEXICAL_BLOCK_RANGES
351 DW_ABRV_LEXICAL_BLOCK_SIMPLE
353 DW_ABRV_FUNCTYPEPARAM
364 DW_ABRV_BARE_PTRTYPE // only for void*, no DW_AT_type attr to please gdb 6.
373 type dwAbbrev struct {
379 var abbrevsFinalized bool
381 // expandPseudoForm takes an input DW_FORM_xxx value and translates it
382 // into a platform-appropriate concrete form. Existing concrete/real
383 // DW_FORM values are left untouched. For the moment the only
384 // pseudo-form is DW_FORM_udata_pseudo, which gets expanded to
385 // DW_FORM_data4 on Darwin and DW_FORM_udata everywhere else. See
386 // issue #31459 for more context.
387 func expandPseudoForm(form uint8) uint8 {
388 // Is this a pseudo-form?
389 if form != DW_FORM_udata_pseudo {
392 expandedForm := DW_FORM_udata
393 if buildcfg.GOOS == "darwin" || buildcfg.GOOS == "ios" {
394 expandedForm = DW_FORM_data4
396 return uint8(expandedForm)
399 // Abbrevs() returns the finalized abbrev array for the platform,
400 // expanding any DW_FORM pseudo-ops to real values.
401 func Abbrevs() []dwAbbrev {
402 if abbrevsFinalized {
405 for i := 1; i < DW_NABRV; i++ {
406 for j := 0; j < len(abbrevs[i].attr); j++ {
407 abbrevs[i].attr[j].form = expandPseudoForm(abbrevs[i].attr[j].form)
410 abbrevsFinalized = true
414 // abbrevs is a raw table of abbrev entries; it needs to be post-processed
415 // by the Abbrevs() function above prior to being consumed, to expand
416 // the 'pseudo-form' entries below to real DWARF form values.
418 var abbrevs = [DW_NABRV]dwAbbrev{
419 /* The mandatory DW_ABRV_NULL entry. */
420 {0, 0, []dwAttrForm{}},
427 {DW_AT_name, DW_FORM_string},
428 {DW_AT_language, DW_FORM_data1},
429 {DW_AT_stmt_list, DW_FORM_sec_offset},
430 {DW_AT_low_pc, DW_FORM_addr},
431 {DW_AT_ranges, DW_FORM_sec_offset},
432 {DW_AT_comp_dir, DW_FORM_string},
433 {DW_AT_producer, DW_FORM_string},
434 {DW_AT_go_package_name, DW_FORM_string},
438 /* COMPUNIT_TEXTLESS */
443 {DW_AT_name, DW_FORM_string},
444 {DW_AT_language, DW_FORM_data1},
445 {DW_AT_comp_dir, DW_FORM_string},
446 {DW_AT_producer, DW_FORM_string},
447 {DW_AT_go_package_name, DW_FORM_string},
456 {DW_AT_name, DW_FORM_string},
457 {DW_AT_low_pc, DW_FORM_addr},
458 {DW_AT_high_pc, DW_FORM_addr},
459 {DW_AT_frame_base, DW_FORM_block1},
460 {DW_AT_decl_file, DW_FORM_data4},
461 {DW_AT_external, DW_FORM_flag},
470 {DW_AT_name, DW_FORM_string},
471 {DW_AT_low_pc, DW_FORM_addr},
472 {DW_AT_high_pc, DW_FORM_addr},
473 {DW_AT_frame_base, DW_FORM_block1},
474 {DW_AT_trampoline, DW_FORM_flag},
478 /* FUNCTION_ABSTRACT */
483 {DW_AT_name, DW_FORM_string},
484 {DW_AT_inline, DW_FORM_data1},
485 {DW_AT_external, DW_FORM_flag},
489 /* FUNCTION_CONCRETE */
494 {DW_AT_abstract_origin, DW_FORM_ref_addr},
495 {DW_AT_low_pc, DW_FORM_addr},
496 {DW_AT_high_pc, DW_FORM_addr},
497 {DW_AT_frame_base, DW_FORM_block1},
501 /* WRAPPER_CONCRETE */
506 {DW_AT_abstract_origin, DW_FORM_ref_addr},
507 {DW_AT_low_pc, DW_FORM_addr},
508 {DW_AT_high_pc, DW_FORM_addr},
509 {DW_AT_frame_base, DW_FORM_block1},
510 {DW_AT_trampoline, DW_FORM_flag},
514 /* INLINED_SUBROUTINE */
516 DW_TAG_inlined_subroutine,
519 {DW_AT_abstract_origin, DW_FORM_ref_addr},
520 {DW_AT_low_pc, DW_FORM_addr},
521 {DW_AT_high_pc, DW_FORM_addr},
522 {DW_AT_call_file, DW_FORM_data4},
523 {DW_AT_call_line, DW_FORM_udata_pseudo}, // pseudo-form
527 /* INLINED_SUBROUTINE_RANGES */
529 DW_TAG_inlined_subroutine,
532 {DW_AT_abstract_origin, DW_FORM_ref_addr},
533 {DW_AT_ranges, DW_FORM_sec_offset},
534 {DW_AT_call_file, DW_FORM_data4},
535 {DW_AT_call_line, DW_FORM_udata_pseudo}, // pseudo-form
544 {DW_AT_name, DW_FORM_string},
545 {DW_AT_location, DW_FORM_block1},
546 {DW_AT_type, DW_FORM_ref_addr},
547 {DW_AT_external, DW_FORM_flag},
556 {DW_AT_name, DW_FORM_string},
557 {DW_AT_type, DW_FORM_ref_addr},
558 {DW_AT_const_value, DW_FORM_sdata},
567 {DW_AT_name, DW_FORM_string},
568 {DW_AT_decl_line, DW_FORM_udata},
569 {DW_AT_type, DW_FORM_ref_addr},
570 {DW_AT_location, DW_FORM_block1},
579 {DW_AT_name, DW_FORM_string},
580 {DW_AT_decl_line, DW_FORM_udata},
581 {DW_AT_type, DW_FORM_ref_addr},
582 {DW_AT_location, DW_FORM_sec_offset},
591 {DW_AT_name, DW_FORM_string},
592 {DW_AT_decl_line, DW_FORM_udata},
593 {DW_AT_type, DW_FORM_ref_addr},
602 {DW_AT_abstract_origin, DW_FORM_ref_addr},
603 {DW_AT_location, DW_FORM_block1},
607 /* AUTO_CONCRETE_LOCLIST */
612 {DW_AT_abstract_origin, DW_FORM_ref_addr},
613 {DW_AT_location, DW_FORM_sec_offset},
619 DW_TAG_formal_parameter,
622 {DW_AT_name, DW_FORM_string},
623 {DW_AT_variable_parameter, DW_FORM_flag},
624 {DW_AT_decl_line, DW_FORM_udata},
625 {DW_AT_type, DW_FORM_ref_addr},
626 {DW_AT_location, DW_FORM_block1},
632 DW_TAG_formal_parameter,
635 {DW_AT_name, DW_FORM_string},
636 {DW_AT_variable_parameter, DW_FORM_flag},
637 {DW_AT_decl_line, DW_FORM_udata},
638 {DW_AT_type, DW_FORM_ref_addr},
639 {DW_AT_location, DW_FORM_sec_offset},
645 DW_TAG_formal_parameter,
648 {DW_AT_name, DW_FORM_string},
649 {DW_AT_variable_parameter, DW_FORM_flag},
650 {DW_AT_type, DW_FORM_ref_addr},
656 DW_TAG_formal_parameter,
659 {DW_AT_abstract_origin, DW_FORM_ref_addr},
660 {DW_AT_location, DW_FORM_block1},
664 /* PARAM_CONCRETE_LOCLIST */
666 DW_TAG_formal_parameter,
669 {DW_AT_abstract_origin, DW_FORM_ref_addr},
670 {DW_AT_location, DW_FORM_sec_offset},
674 /* LEXICAL_BLOCK_RANGES */
676 DW_TAG_lexical_block,
679 {DW_AT_ranges, DW_FORM_sec_offset},
683 /* LEXICAL_BLOCK_SIMPLE */
685 DW_TAG_lexical_block,
688 {DW_AT_low_pc, DW_FORM_addr},
689 {DW_AT_high_pc, DW_FORM_addr},
698 {DW_AT_name, DW_FORM_string},
699 {DW_AT_data_member_location, DW_FORM_udata},
700 {DW_AT_type, DW_FORM_ref_addr},
701 {DW_AT_go_embedded_field, DW_FORM_flag},
707 DW_TAG_formal_parameter,
712 {DW_AT_type, DW_FORM_ref_addr},
718 DW_TAG_unspecified_parameters,
725 DW_TAG_subrange_type,
730 {DW_AT_type, DW_FORM_ref_addr},
731 {DW_AT_count, DW_FORM_udata},
735 // Below here are the types considered public by ispubtype
738 DW_TAG_unspecified_type,
741 {DW_AT_name, DW_FORM_string},
750 {DW_AT_name, DW_FORM_string},
751 {DW_AT_encoding, DW_FORM_data1},
752 {DW_AT_byte_size, DW_FORM_data1},
753 {DW_AT_go_kind, DW_FORM_data1},
754 {DW_AT_go_runtime_type, DW_FORM_addr},
759 // child is subrange with upper bound
764 {DW_AT_name, DW_FORM_string},
765 {DW_AT_type, DW_FORM_ref_addr},
766 {DW_AT_byte_size, DW_FORM_udata},
767 {DW_AT_go_kind, DW_FORM_data1},
768 {DW_AT_go_runtime_type, DW_FORM_addr},
777 {DW_AT_name, DW_FORM_string},
778 {DW_AT_type, DW_FORM_ref_addr},
779 {DW_AT_go_kind, DW_FORM_data1},
780 {DW_AT_go_runtime_type, DW_FORM_addr},
781 {DW_AT_go_elem, DW_FORM_ref_addr},
787 DW_TAG_subroutine_type,
790 {DW_AT_name, DW_FORM_string},
791 {DW_AT_byte_size, DW_FORM_udata},
792 {DW_AT_go_kind, DW_FORM_data1},
793 {DW_AT_go_runtime_type, DW_FORM_addr},
802 {DW_AT_name, DW_FORM_string},
803 {DW_AT_type, DW_FORM_ref_addr},
804 {DW_AT_go_kind, DW_FORM_data1},
805 {DW_AT_go_runtime_type, DW_FORM_addr},
814 {DW_AT_name, DW_FORM_string},
815 {DW_AT_type, DW_FORM_ref_addr},
816 {DW_AT_go_kind, DW_FORM_data1},
817 {DW_AT_go_runtime_type, DW_FORM_addr},
818 {DW_AT_go_key, DW_FORM_ref_addr},
819 {DW_AT_go_elem, DW_FORM_ref_addr},
828 {DW_AT_name, DW_FORM_string},
829 {DW_AT_type, DW_FORM_ref_addr},
830 {DW_AT_go_kind, DW_FORM_data1},
831 {DW_AT_go_runtime_type, DW_FORM_addr},
840 {DW_AT_name, DW_FORM_string},
846 DW_TAG_structure_type,
849 {DW_AT_name, DW_FORM_string},
850 {DW_AT_byte_size, DW_FORM_udata},
851 {DW_AT_go_kind, DW_FORM_data1},
852 {DW_AT_go_runtime_type, DW_FORM_addr},
853 {DW_AT_go_elem, DW_FORM_ref_addr},
859 DW_TAG_structure_type,
862 {DW_AT_name, DW_FORM_string},
863 {DW_AT_byte_size, DW_FORM_udata},
864 {DW_AT_go_kind, DW_FORM_data1},
865 {DW_AT_go_runtime_type, DW_FORM_addr},
871 DW_TAG_structure_type,
874 {DW_AT_name, DW_FORM_string},
875 {DW_AT_byte_size, DW_FORM_udata},
876 {DW_AT_go_kind, DW_FORM_data1},
877 {DW_AT_go_runtime_type, DW_FORM_addr},
886 {DW_AT_name, DW_FORM_string},
887 {DW_AT_type, DW_FORM_ref_addr},
896 {DW_AT_name, DW_FORM_string},
897 {DW_AT_type, DW_FORM_ref_addr},
898 {DW_AT_go_dict_index, DW_FORM_udata},
903 // GetAbbrev returns the contents of the .debug_abbrev section.
904 func GetAbbrev() []byte {
907 for i := 1; i < DW_NABRV; i++ {
909 buf = AppendUleb128(buf, uint64(i))
910 buf = AppendUleb128(buf, uint64(abbrevs[i].tag))
911 buf = append(buf, abbrevs[i].children)
912 for _, f := range abbrevs[i].attr {
913 buf = AppendUleb128(buf, uint64(f.attr))
914 buf = AppendUleb128(buf, uint64(f.form))
916 buf = append(buf, 0, 0)
918 return append(buf, 0)
922 * Debugging Information Entries and their attributes.
925 // DWAttr represents an attribute of a DWDie.
927 // For DW_CLS_string and _block, value should contain the length, and
928 // data the data, for _reference, value is 0 and data is a DWDie* to
929 // the referenced instance, for all others, value is the whole thing
939 // DWDie represents a DWARF debug info entry.
948 func putattr(ctxt Context, s Sym, abbrev int, form int, cls int, value int64, data interface{}) error {
950 case DW_FORM_addr: // address
951 // Allow nil addresses for DW_AT_go_runtime_type.
952 if data == nil && value == 0 {
953 ctxt.AddInt(s, ctxt.PtrSize(), 0)
956 if cls == DW_CLS_GO_TYPEREF {
957 ctxt.AddSectionOffset(s, ctxt.PtrSize(), data, value)
960 ctxt.AddAddress(s, data, value)
962 case DW_FORM_block1: // block
963 if cls == DW_CLS_ADDRESS {
964 ctxt.AddInt(s, 1, int64(1+ctxt.PtrSize()))
965 ctxt.AddInt(s, 1, DW_OP_addr)
966 ctxt.AddAddress(s, data, 0)
971 ctxt.AddInt(s, 1, value)
972 p := data.([]byte)[:value]
975 case DW_FORM_block2: // block
978 ctxt.AddInt(s, 2, value)
979 p := data.([]byte)[:value]
982 case DW_FORM_block4: // block
985 ctxt.AddInt(s, 4, value)
986 p := data.([]byte)[:value]
989 case DW_FORM_block: // block
990 Uleb128put(ctxt, s, value)
992 p := data.([]byte)[:value]
995 case DW_FORM_data1: // constant
996 ctxt.AddInt(s, 1, value)
998 case DW_FORM_data2: // constant
999 ctxt.AddInt(s, 2, value)
1001 case DW_FORM_data4: // constant, {line,loclist,mac,rangelist}ptr
1002 if cls == DW_CLS_PTR { // DW_AT_stmt_list and DW_AT_ranges
1003 ctxt.AddDWARFAddrSectionOffset(s, data, value)
1006 ctxt.AddInt(s, 4, value)
1008 case DW_FORM_data8: // constant, {line,loclist,mac,rangelist}ptr
1009 ctxt.AddInt(s, 8, value)
1011 case DW_FORM_sdata: // constant
1012 Sleb128put(ctxt, s, value)
1014 case DW_FORM_udata: // constant
1015 Uleb128put(ctxt, s, value)
1017 case DW_FORM_string: // string
1018 str := data.(string)
1019 ctxt.AddString(s, str)
1020 // TODO(ribrdb): verify padded strings are never used and remove this
1021 for i := int64(len(str)); i < value; i++ {
1022 ctxt.AddInt(s, 1, 0)
1025 case DW_FORM_flag: // flag
1027 ctxt.AddInt(s, 1, 1)
1029 ctxt.AddInt(s, 1, 0)
1032 // As of DWARF 3 the ref_addr is always 32 bits, unless emitting a large
1033 // (> 4 GB of debug info aka "64-bit") unit, which we don't implement.
1034 case DW_FORM_ref_addr: // reference to a DIE in the .info section
1036 case DW_FORM_sec_offset: // offset into a DWARF section other than .info
1038 return fmt.Errorf("dwarf: null reference in %d", abbrev)
1040 ctxt.AddDWARFAddrSectionOffset(s, data, value)
1042 case DW_FORM_ref1, // reference within the compilation unit
1043 DW_FORM_ref2, // reference
1044 DW_FORM_ref4, // reference
1045 DW_FORM_ref8, // reference
1046 DW_FORM_ref_udata, // reference
1048 DW_FORM_strp, // string
1049 DW_FORM_indirect: // (see Section 7.5.3)
1052 return fmt.Errorf("dwarf: unsupported attribute form %d / class %d", form, cls)
1057 // PutAttrs writes the attributes for a DIE to symbol 's'.
1059 // Note that we can (and do) add arbitrary attributes to a DIE, but
1060 // only the ones actually listed in the Abbrev will be written out.
1061 func PutAttrs(ctxt Context, s Sym, abbrev int, attr *DWAttr) {
1062 abbrevs := Abbrevs()
1064 for _, f := range abbrevs[abbrev].attr {
1065 for ap := attr; ap != nil; ap = ap.Link {
1066 if ap.Atr == f.attr {
1067 putattr(ctxt, s, abbrev, int(f.form), int(ap.Cls), ap.Value, ap.Data)
1072 putattr(ctxt, s, abbrev, int(f.form), 0, 0, nil)
1076 // HasChildren reports whether 'die' uses an abbrev that supports children.
1077 func HasChildren(die *DWDie) bool {
1078 abbrevs := Abbrevs()
1079 return abbrevs[die.Abbrev].children != 0
1082 // PutIntConst writes a DIE for an integer constant
1083 func PutIntConst(ctxt Context, info, typ Sym, name string, val int64) {
1084 Uleb128put(ctxt, info, DW_ABRV_INT_CONSTANT)
1085 putattr(ctxt, info, DW_ABRV_INT_CONSTANT, DW_FORM_string, DW_CLS_STRING, int64(len(name)), name)
1086 putattr(ctxt, info, DW_ABRV_INT_CONSTANT, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, typ)
1087 putattr(ctxt, info, DW_ABRV_INT_CONSTANT, DW_FORM_sdata, DW_CLS_CONSTANT, val, nil)
1090 // PutGlobal writes a DIE for a global variable.
1091 func PutGlobal(ctxt Context, info, typ, gvar Sym, name string) {
1092 Uleb128put(ctxt, info, DW_ABRV_VARIABLE)
1093 putattr(ctxt, info, DW_ABRV_VARIABLE, DW_FORM_string, DW_CLS_STRING, int64(len(name)), name)
1094 putattr(ctxt, info, DW_ABRV_VARIABLE, DW_FORM_block1, DW_CLS_ADDRESS, 0, gvar)
1095 putattr(ctxt, info, DW_ABRV_VARIABLE, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, typ)
1096 putattr(ctxt, info, DW_ABRV_VARIABLE, DW_FORM_flag, DW_CLS_FLAG, 1, nil)
1099 // PutBasedRanges writes a range table to sym. All addresses in ranges are
1100 // relative to some base address, which must be arranged by the caller
1101 // (e.g., with a DW_AT_low_pc attribute, or in a BASE-prefixed range).
1102 func PutBasedRanges(ctxt Context, sym Sym, ranges []Range) {
1103 ps := ctxt.PtrSize()
1105 for _, r := range ranges {
1106 ctxt.AddInt(sym, ps, r.Start)
1107 ctxt.AddInt(sym, ps, r.End)
1110 ctxt.AddInt(sym, ps, 0)
1111 ctxt.AddInt(sym, ps, 0)
1114 // PutRanges writes a range table to s.Ranges.
1115 // All addresses in ranges are relative to s.base.
1116 func (s *FnState) PutRanges(ctxt Context, ranges []Range) {
1117 ps := ctxt.PtrSize()
1118 sym, base := s.Ranges, s.StartPC
1120 if s.UseBASEntries {
1121 // Using a Base Address Selection Entry reduces the number of relocations, but
1122 // this is not done on macOS because it is not supported by dsymutil/dwarfdump/lldb
1123 ctxt.AddInt(sym, ps, -1)
1124 ctxt.AddAddress(sym, base, 0)
1125 PutBasedRanges(ctxt, sym, ranges)
1129 // Write ranges full of relocations
1130 for _, r := range ranges {
1131 ctxt.AddCURelativeAddress(sym, base, r.Start)
1132 ctxt.AddCURelativeAddress(sym, base, r.End)
1135 ctxt.AddInt(sym, ps, 0)
1136 ctxt.AddInt(sym, ps, 0)
1139 // Return TRUE if the inlined call in the specified slot is empty,
1140 // meaning it has a zero-length range (no instructions), and all
1141 // of its children are empty.
1142 func isEmptyInlinedCall(slot int, calls *InlCalls) bool {
1143 ic := &calls.Calls[slot]
1144 if ic.InlIndex == -2 {
1148 for _, k := range ic.Children {
1149 if !isEmptyInlinedCall(k, calls) {
1153 if len(ic.Ranges) > 0 {
1162 // Slot -1: return top-level inlines
1163 // Slot >= 0: return children of that slot
1164 func inlChildren(slot int, calls *InlCalls) []int {
1167 for _, k := range calls.Calls[slot].Children {
1168 if !isEmptyInlinedCall(k, calls) {
1169 kids = append(kids, k)
1173 for k := 0; k < len(calls.Calls); k += 1 {
1174 if calls.Calls[k].Root && !isEmptyInlinedCall(k, calls) {
1175 kids = append(kids, k)
1182 func inlinedVarTable(inlcalls *InlCalls) map[*Var]bool {
1183 vars := make(map[*Var]bool)
1184 for _, ic := range inlcalls.Calls {
1185 for _, v := range ic.InlVars {
1192 // The s.Scopes slice contains variables were originally part of the
1193 // function being emitted, as well as variables that were imported
1194 // from various callee functions during the inlining process. This
1195 // function prunes out any variables from the latter category (since
1196 // they will be emitted as part of DWARF inlined_subroutine DIEs) and
1197 // then generates scopes for vars in the former category.
1198 func putPrunedScopes(ctxt Context, s *FnState, fnabbrev int) error {
1199 if len(s.Scopes) == 0 {
1202 scopes := make([]Scope, len(s.Scopes), len(s.Scopes))
1203 pvars := inlinedVarTable(&s.InlCalls)
1204 for k, s := range s.Scopes {
1205 var pruned Scope = Scope{Parent: s.Parent, Ranges: s.Ranges}
1206 for i := 0; i < len(s.Vars); i++ {
1207 _, found := pvars[s.Vars[i]]
1209 pruned.Vars = append(pruned.Vars, s.Vars[i])
1212 sort.Sort(byChildIndex(pruned.Vars))
1216 s.dictIndexToOffset = putparamtypes(ctxt, s, scopes, fnabbrev)
1219 if putscope(ctxt, s, scopes, 0, fnabbrev, encbuf[:0]) < int32(len(scopes)) {
1220 return errors.New("multiple toplevel scopes")
1225 // Emit DWARF attributes and child DIEs for an 'abstract' subprogram.
1226 // The abstract subprogram DIE for a function contains its
1227 // location-independent attributes (name, type, etc). Other instances
1228 // of the function (any inlined copy of it, or the single out-of-line
1229 // 'concrete' instance) will contain a pointer back to this abstract
1230 // DIE (as a space-saving measure, so that name/type etc doesn't have
1231 // to be repeated for each inlined copy).
1232 func PutAbstractFunc(ctxt Context, s *FnState) error {
1235 ctxt.Logf("PutAbstractFunc(%v)\n", s.Absfn)
1238 abbrev := DW_ABRV_FUNCTION_ABSTRACT
1239 Uleb128put(ctxt, s.Absfn, int64(abbrev))
1242 if strings.HasPrefix(s.Name, "\"\".") {
1243 // Generate a fully qualified name for the function in the
1244 // abstract case. This is so as to avoid the need for the
1245 // linker to process the DIE with patchDWARFName(); we can't
1246 // allow the name attribute of an abstract subprogram DIE to
1247 // be rewritten, since it would change the offsets of the
1248 // child DIEs (which we're relying on in order for abstract
1249 // origin references to work).
1250 fullname = objabi.PathToPrefix(s.Importpath) + "." + s.Name[3:]
1252 putattr(ctxt, s.Absfn, abbrev, DW_FORM_string, DW_CLS_STRING, int64(len(fullname)), fullname)
1254 // DW_AT_inlined value
1255 putattr(ctxt, s.Absfn, abbrev, DW_FORM_data1, DW_CLS_CONSTANT, int64(DW_INL_inlined), nil)
1261 putattr(ctxt, s.Absfn, abbrev, DW_FORM_flag, DW_CLS_FLAG, ev, 0)
1263 // Child variables (may be empty)
1264 var flattened []*Var
1266 // This slice will hold the offset in bytes for each child var DIE
1267 // with respect to the start of the parent subprogram DIE.
1271 if len(s.Scopes) > 0 {
1272 // For abstract subprogram DIEs we want to flatten out scope info:
1273 // lexical scope DIEs contain range and/or hi/lo PC attributes,
1274 // which we explicitly don't want for the abstract subprogram DIE.
1275 pvars := inlinedVarTable(&s.InlCalls)
1276 for _, scope := range s.Scopes {
1277 for i := 0; i < len(scope.Vars); i++ {
1278 _, found := pvars[scope.Vars[i]]
1279 if found || !scope.Vars[i].IsInAbstract {
1282 flattened = append(flattened, scope.Vars[i])
1285 if len(flattened) > 0 {
1286 sort.Sort(byChildIndex(flattened))
1289 ctxt.Logf("putAbstractScope(%v): vars:", s.Info)
1290 for i, v := range flattened {
1291 ctxt.Logf(" %d:%s", i, v.Name)
1296 // This slice will hold the offset in bytes for each child
1297 // variable DIE with respect to the start of the parent
1299 for _, v := range flattened {
1300 offsets = append(offsets, int32(ctxt.CurrentOffset(s.Absfn)))
1301 putAbstractVar(ctxt, s.Absfn, v)
1305 ctxt.RecordChildDieOffsets(s.Absfn, flattened, offsets)
1307 Uleb128put(ctxt, s.Absfn, 0)
1311 // Emit DWARF attributes and child DIEs for an inlined subroutine. The
1312 // first attribute of an inlined subroutine DIE is a reference back to
1313 // its corresponding 'abstract' DIE (containing location-independent
1314 // attributes such as name, type, etc). Inlined subroutine DIEs can
1315 // have other inlined subroutine DIEs as children.
1316 func putInlinedFunc(ctxt Context, s *FnState, callIdx int) error {
1317 ic := s.InlCalls.Calls[callIdx]
1318 callee := ic.AbsFunSym
1320 abbrev := DW_ABRV_INLINED_SUBROUTINE_RANGES
1321 if len(ic.Ranges) == 1 {
1322 abbrev = DW_ABRV_INLINED_SUBROUTINE
1324 Uleb128put(ctxt, s.Info, int64(abbrev))
1327 ctxt.Logf("putInlinedFunc(callee=%v,abbrev=%d)\n", callee, abbrev)
1331 putattr(ctxt, s.Info, abbrev, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, callee)
1333 if abbrev == DW_ABRV_INLINED_SUBROUTINE_RANGES {
1334 putattr(ctxt, s.Info, abbrev, DW_FORM_sec_offset, DW_CLS_PTR, s.Ranges.Length(ctxt), s.Ranges)
1335 s.PutRanges(ctxt, ic.Ranges)
1337 st := ic.Ranges[0].Start
1338 en := ic.Ranges[0].End
1339 putattr(ctxt, s.Info, abbrev, DW_FORM_addr, DW_CLS_ADDRESS, st, s.StartPC)
1340 putattr(ctxt, s.Info, abbrev, DW_FORM_addr, DW_CLS_ADDRESS, en, s.StartPC)
1343 // Emit call file, line attrs.
1344 ctxt.AddFileRef(s.Info, ic.CallFile)
1345 form := int(expandPseudoForm(DW_FORM_udata_pseudo))
1346 putattr(ctxt, s.Info, abbrev, form, DW_CLS_CONSTANT, int64(ic.CallLine), nil)
1348 // Variables associated with this inlined routine instance.
1350 sort.Sort(byChildIndex(vars))
1351 inlIndex := ic.InlIndex
1353 for _, v := range vars {
1354 if !v.IsInAbstract {
1357 putvar(ctxt, s, v, callee, abbrev, inlIndex, encbuf[:0])
1360 // Children of this inline.
1361 for _, sib := range inlChildren(callIdx, &s.InlCalls) {
1362 err := putInlinedFunc(ctxt, s, sib)
1368 Uleb128put(ctxt, s.Info, 0)
1372 // Emit DWARF attributes and child DIEs for a 'concrete' subprogram,
1373 // meaning the out-of-line copy of a function that was inlined at some
1374 // point during the compilation of its containing package. The first
1375 // attribute for a concrete DIE is a reference to the 'abstract' DIE
1376 // for the function (which holds location-independent attributes such
1377 // as name, type), then the remainder of the attributes are specific
1378 // to this instance (location, frame base, etc).
1379 func PutConcreteFunc(ctxt Context, s *FnState, isWrapper bool) error {
1381 ctxt.Logf("PutConcreteFunc(%v)\n", s.Info)
1383 abbrev := DW_ABRV_FUNCTION_CONCRETE
1385 abbrev = DW_ABRV_WRAPPER_CONCRETE
1387 Uleb128put(ctxt, s.Info, int64(abbrev))
1390 putattr(ctxt, s.Info, abbrev, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, s.Absfn)
1393 putattr(ctxt, s.Info, abbrev, DW_FORM_addr, DW_CLS_ADDRESS, 0, s.StartPC)
1394 putattr(ctxt, s.Info, abbrev, DW_FORM_addr, DW_CLS_ADDRESS, s.Size, s.StartPC)
1397 putattr(ctxt, s.Info, abbrev, DW_FORM_block1, DW_CLS_BLOCK, 1, []byte{DW_OP_call_frame_cfa})
1400 putattr(ctxt, s.Info, abbrev, DW_FORM_flag, DW_CLS_FLAG, int64(1), 0)
1404 if err := putPrunedScopes(ctxt, s, abbrev); err != nil {
1408 // Inlined subroutines.
1409 for _, sib := range inlChildren(-1, &s.InlCalls) {
1410 err := putInlinedFunc(ctxt, s, sib)
1416 Uleb128put(ctxt, s.Info, 0)
1420 // Emit DWARF attributes and child DIEs for a subprogram. Here
1421 // 'default' implies that the function in question was not inlined
1422 // when its containing package was compiled (hence there is no need to
1423 // emit an abstract version for it to use as a base for inlined
1424 // routine records).
1425 func PutDefaultFunc(ctxt Context, s *FnState, isWrapper bool) error {
1427 ctxt.Logf("PutDefaultFunc(%v)\n", s.Info)
1429 abbrev := DW_ABRV_FUNCTION
1431 abbrev = DW_ABRV_WRAPPER
1433 Uleb128put(ctxt, s.Info, int64(abbrev))
1435 // Expand '"".' to import path.
1437 if s.Importpath != "" {
1438 name = strings.Replace(name, "\"\".", objabi.PathToPrefix(s.Importpath)+".", -1)
1441 putattr(ctxt, s.Info, DW_ABRV_FUNCTION, DW_FORM_string, DW_CLS_STRING, int64(len(name)), name)
1442 putattr(ctxt, s.Info, abbrev, DW_FORM_addr, DW_CLS_ADDRESS, 0, s.StartPC)
1443 putattr(ctxt, s.Info, abbrev, DW_FORM_addr, DW_CLS_ADDRESS, s.Size, s.StartPC)
1444 putattr(ctxt, s.Info, abbrev, DW_FORM_block1, DW_CLS_BLOCK, 1, []byte{DW_OP_call_frame_cfa})
1446 putattr(ctxt, s.Info, abbrev, DW_FORM_flag, DW_CLS_FLAG, int64(1), 0)
1448 ctxt.AddFileRef(s.Info, s.Filesym)
1453 putattr(ctxt, s.Info, abbrev, DW_FORM_flag, DW_CLS_FLAG, ev, 0)
1457 if err := putPrunedScopes(ctxt, s, abbrev); err != nil {
1461 // Inlined subroutines.
1462 for _, sib := range inlChildren(-1, &s.InlCalls) {
1463 err := putInlinedFunc(ctxt, s, sib)
1469 Uleb128put(ctxt, s.Info, 0)
1473 // putparamtypes writes typedef DIEs for any parametric types that are used by this function.
1474 func putparamtypes(ctxt Context, s *FnState, scopes []Scope, fnabbrev int) []int64 {
1475 if fnabbrev == DW_ABRV_FUNCTION_CONCRETE {
1479 maxDictIndex := uint16(0)
1481 for i := range scopes {
1482 for _, v := range scopes[i].Vars {
1483 if v.DictIndex > maxDictIndex {
1484 maxDictIndex = v.DictIndex
1489 if maxDictIndex == 0 {
1493 dictIndexToOffset := make([]int64, maxDictIndex)
1495 for i := range scopes {
1496 for _, v := range scopes[i].Vars {
1497 if v.DictIndex == 0 || dictIndexToOffset[v.DictIndex-1] != 0 {
1501 dictIndexToOffset[v.DictIndex-1] = ctxt.CurrentOffset(s.Info)
1503 Uleb128put(ctxt, s.Info, int64(DW_ABRV_DICT_INDEX))
1504 n := fmt.Sprintf(".param%d", v.DictIndex-1)
1505 putattr(ctxt, s.Info, DW_ABRV_DICT_INDEX, DW_FORM_string, DW_CLS_STRING, int64(len(n)), n)
1506 putattr(ctxt, s.Info, DW_ABRV_DICT_INDEX, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, v.Type)
1507 putattr(ctxt, s.Info, DW_ABRV_DICT_INDEX, DW_FORM_udata, DW_CLS_CONSTANT, int64(v.DictIndex-1), nil)
1511 return dictIndexToOffset
1514 func putscope(ctxt Context, s *FnState, scopes []Scope, curscope int32, fnabbrev int, encbuf []byte) int32 {
1517 ctxt.Logf("putscope(%v,%d): vars:", s.Info, curscope)
1518 for i, v := range scopes[curscope].Vars {
1519 ctxt.Logf(" %d:%d:%s", i, v.ChildIndex, v.Name)
1524 for _, v := range scopes[curscope].Vars {
1525 putvar(ctxt, s, v, s.Absfn, fnabbrev, -1, encbuf)
1529 for curscope < int32(len(scopes)) {
1530 scope := scopes[curscope]
1531 if scope.Parent != this {
1535 if len(scopes[curscope].Vars) == 0 {
1536 curscope = putscope(ctxt, s, scopes, curscope, fnabbrev, encbuf)
1540 if len(scope.Ranges) == 1 {
1541 Uleb128put(ctxt, s.Info, DW_ABRV_LEXICAL_BLOCK_SIMPLE)
1542 putattr(ctxt, s.Info, DW_ABRV_LEXICAL_BLOCK_SIMPLE, DW_FORM_addr, DW_CLS_ADDRESS, scope.Ranges[0].Start, s.StartPC)
1543 putattr(ctxt, s.Info, DW_ABRV_LEXICAL_BLOCK_SIMPLE, DW_FORM_addr, DW_CLS_ADDRESS, scope.Ranges[0].End, s.StartPC)
1545 Uleb128put(ctxt, s.Info, DW_ABRV_LEXICAL_BLOCK_RANGES)
1546 putattr(ctxt, s.Info, DW_ABRV_LEXICAL_BLOCK_RANGES, DW_FORM_sec_offset, DW_CLS_PTR, s.Ranges.Length(ctxt), s.Ranges)
1548 s.PutRanges(ctxt, scope.Ranges)
1551 curscope = putscope(ctxt, s, scopes, curscope, fnabbrev, encbuf)
1553 Uleb128put(ctxt, s.Info, 0)
1558 // Given a default var abbrev code, select corresponding concrete code.
1559 func concreteVarAbbrev(varAbbrev int) int {
1562 return DW_ABRV_AUTO_CONCRETE
1564 return DW_ABRV_PARAM_CONCRETE
1565 case DW_ABRV_AUTO_LOCLIST:
1566 return DW_ABRV_AUTO_CONCRETE_LOCLIST
1567 case DW_ABRV_PARAM_LOCLIST:
1568 return DW_ABRV_PARAM_CONCRETE_LOCLIST
1570 panic("should never happen")
1574 // Pick the correct abbrev code for variable or parameter DIE.
1575 func determineVarAbbrev(v *Var, fnabbrev int) (int, bool, bool) {
1578 // If the variable was entirely optimized out, don't emit a location list;
1579 // convert to an inline abbreviation and emit an empty location.
1582 case abbrev == DW_ABRV_AUTO_LOCLIST && v.PutLocationList == nil:
1584 abbrev = DW_ABRV_AUTO
1585 case abbrev == DW_ABRV_PARAM_LOCLIST && v.PutLocationList == nil:
1587 abbrev = DW_ABRV_PARAM
1590 // Determine whether to use a concrete variable or regular variable DIE.
1593 case DW_ABRV_FUNCTION, DW_ABRV_WRAPPER:
1596 case DW_ABRV_FUNCTION_CONCRETE, DW_ABRV_WRAPPER_CONCRETE:
1597 // If we're emitting a concrete subprogram DIE and the variable
1598 // in question is not part of the corresponding abstract function DIE,
1599 // then use the default (non-concrete) abbrev for this param.
1600 if !v.IsInAbstract {
1603 case DW_ABRV_INLINED_SUBROUTINE, DW_ABRV_INLINED_SUBROUTINE_RANGES:
1605 panic("should never happen")
1608 // Select proper abbrev based on concrete/non-concrete
1610 abbrev = concreteVarAbbrev(abbrev)
1613 return abbrev, missing, concrete
1616 func abbrevUsesLoclist(abbrev int) bool {
1618 case DW_ABRV_AUTO_LOCLIST, DW_ABRV_AUTO_CONCRETE_LOCLIST,
1619 DW_ABRV_PARAM_LOCLIST, DW_ABRV_PARAM_CONCRETE_LOCLIST:
1626 // Emit DWARF attributes for a variable belonging to an 'abstract' subprogram.
1627 func putAbstractVar(ctxt Context, info Sym, v *Var) {
1631 case DW_ABRV_AUTO, DW_ABRV_AUTO_LOCLIST:
1632 abbrev = DW_ABRV_AUTO_ABSTRACT
1633 case DW_ABRV_PARAM, DW_ABRV_PARAM_LOCLIST:
1634 abbrev = DW_ABRV_PARAM_ABSTRACT
1637 Uleb128put(ctxt, info, int64(abbrev))
1638 putattr(ctxt, info, abbrev, DW_FORM_string, DW_CLS_STRING, int64(len(v.Name)), v.Name)
1640 // Isreturn attribute if this is a param
1641 if abbrev == DW_ABRV_PARAM_ABSTRACT {
1643 if v.IsReturnValue {
1646 putattr(ctxt, info, abbrev, DW_FORM_flag, DW_CLS_FLAG, isReturn, nil)
1650 if abbrev != DW_ABRV_PARAM_ABSTRACT {
1651 // See issue 23374 for more on why decl line is skipped for abs params.
1652 putattr(ctxt, info, abbrev, DW_FORM_udata, DW_CLS_CONSTANT, int64(v.DeclLine), nil)
1656 putattr(ctxt, info, abbrev, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, v.Type)
1658 // Var has no children => no terminator
1661 func putvar(ctxt Context, s *FnState, v *Var, absfn Sym, fnabbrev, inlIndex int, encbuf []byte) {
1662 // Remap abbrev according to parent DIE abbrev
1663 abbrev, missing, concrete := determineVarAbbrev(v, fnabbrev)
1665 Uleb128put(ctxt, s.Info, int64(abbrev))
1667 // Abstract origin for concrete / inlined case
1669 // Here we are making a reference to a child DIE of an abstract
1670 // function subprogram DIE. The child DIE has no LSym, so instead
1671 // after the call to 'putattr' below we make a call to register
1672 // the child DIE reference.
1673 putattr(ctxt, s.Info, abbrev, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, absfn)
1674 ctxt.RecordDclReference(s.Info, absfn, int(v.ChildIndex), inlIndex)
1676 // Var name, line for abstract and default cases
1678 putattr(ctxt, s.Info, abbrev, DW_FORM_string, DW_CLS_STRING, int64(len(n)), n)
1679 if abbrev == DW_ABRV_PARAM || abbrev == DW_ABRV_PARAM_LOCLIST || abbrev == DW_ABRV_PARAM_ABSTRACT {
1681 if v.IsReturnValue {
1684 putattr(ctxt, s.Info, abbrev, DW_FORM_flag, DW_CLS_FLAG, isReturn, nil)
1686 putattr(ctxt, s.Info, abbrev, DW_FORM_udata, DW_CLS_CONSTANT, int64(v.DeclLine), nil)
1687 if v.DictIndex > 0 && s.dictIndexToOffset != nil && s.dictIndexToOffset[v.DictIndex-1] != 0 {
1688 // If the type of this variable is parametric use the entry emitted by putparamtypes
1689 putattr(ctxt, s.Info, abbrev, DW_FORM_ref_addr, DW_CLS_REFERENCE, s.dictIndexToOffset[v.DictIndex-1], s.Info)
1691 putattr(ctxt, s.Info, abbrev, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, v.Type)
1695 if abbrevUsesLoclist(abbrev) {
1696 putattr(ctxt, s.Info, abbrev, DW_FORM_sec_offset, DW_CLS_PTR, s.Loc.Length(ctxt), s.Loc)
1697 v.PutLocationList(s.Loc, s.StartPC)
1702 break // no location
1703 case v.StackOffset == 0:
1704 loc = append(loc, DW_OP_call_frame_cfa)
1706 loc = append(loc, DW_OP_fbreg)
1707 loc = AppendSleb128(loc, int64(v.StackOffset))
1709 putattr(ctxt, s.Info, abbrev, DW_FORM_block1, DW_CLS_BLOCK, int64(len(loc)), loc)
1712 // Var has no children => no terminator
1715 // byChildIndex implements sort.Interface for []*dwarf.Var by child index.
1716 type byChildIndex []*Var
1718 func (s byChildIndex) Len() int { return len(s) }
1719 func (s byChildIndex) Less(i, j int) bool { return s[i].ChildIndex < s[j].ChildIndex }
1720 func (s byChildIndex) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
1722 // IsDWARFEnabledOnAIX returns true if DWARF is possible on the
1724 // AIX ld doesn't support DWARF with -bnoobjreorder with version
1726 func IsDWARFEnabledOnAIXLd(extld []string) (bool, error) {
1727 name, args := extld[0], extld[1:]
1728 args = append(args, "-Wl,-V")
1729 out, err := exec.Command(name, args...).CombinedOutput()
1731 // The normal output should display ld version and
1732 // then fails because ".main" is not defined:
1733 // ld: 0711-317 ERROR: Undefined symbol: .main
1734 if !bytes.Contains(out, []byte("0711-317")) {
1735 return false, fmt.Errorf("%s -Wl,-V failed: %v\n%s", extld, err, out)
1738 // gcc -Wl,-V output should be:
1739 // /usr/bin/ld: LD X.X.X(date)
1741 out = bytes.TrimPrefix(out, []byte("/usr/bin/ld: LD "))
1742 vers := string(bytes.Split(out, []byte("("))[0])
1743 subvers := strings.Split(vers, ".")
1744 if len(subvers) != 3 {
1745 return false, fmt.Errorf("cannot parse %s -Wl,-V (%s): %v\n", extld, out, err)
1747 if v, err := strconv.Atoi(subvers[0]); err != nil || v < 7 {
1752 if v, err := strconv.Atoi(subvers[1]); err != nil || v < 2 {
1757 if v, err := strconv.Atoi(subvers[2]); err != nil || v < 2 {