Help us shape the future of Go! Take the 2026 Go Developer Survey

Source file src/cmd/internal/dwarf/dwarf.go

     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.
     4  
     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.
     8  package dwarf
     9  
    10  import (
    11  	"bytes"
    12  	"cmd/internal/src"
    13  	"cmp"
    14  	"errors"
    15  	"fmt"
    16  	"internal/buildcfg"
    17  	"os/exec"
    18  	"slices"
    19  	"strconv"
    20  	"strings"
    21  )
    22  
    23  // InfoPrefix is the prefix for all the symbols containing DWARF info entries.
    24  const InfoPrefix = "go:info."
    25  
    26  // ConstInfoPrefix is the prefix for all symbols containing DWARF info
    27  // entries that contain constants.
    28  const ConstInfoPrefix = "go:constinfo."
    29  
    30  // CUInfoPrefix is the prefix for symbols containing information to
    31  // populate the DWARF compilation unit info entries.
    32  const CUInfoPrefix = "go:cuinfo."
    33  
    34  // Used to form the symbol name assigned to the DWARF "abstract subprogram"
    35  // info entry for a function
    36  const AbstractFuncSuffix = "$abstract"
    37  
    38  // Controls logging/debugging for selected aspects of DWARF subprogram
    39  // generation (functions, scopes).
    40  var logDwarf bool
    41  
    42  // Sym represents a symbol.
    43  type Sym any
    44  
    45  // A Var represents a local variable or a function parameter.
    46  type Var struct {
    47  	Name          string
    48  	Tag           int // Either DW_TAG_variable or DW_TAG_formal_parameter
    49  	WithLoclist   bool
    50  	IsReturnValue bool
    51  	IsInlFormal   bool
    52  	DictIndex     uint16 // index of the dictionary entry describing the type of this variable
    53  	StackOffset   int32
    54  	// This package can't use the ssa package, so it can't mention ssa.FuncDebug,
    55  	// so indirect through a closure.
    56  	PutLocationList func(listSym, startPC Sym)
    57  	Scope           int32
    58  	Type            Sym
    59  	DeclFile        string
    60  	DeclLine        uint
    61  	DeclCol         uint
    62  	InlIndex        int32 // subtract 1 to form real index into InlTree
    63  	ChildIndex      int32 // child DIE index in abstract function
    64  	IsInAbstract    bool  // variable exists in abstract function
    65  	ClosureOffset   int64 // if non-zero this is the offset of this variable in the closure struct
    66  }
    67  
    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
    73  // in this scope.
    74  type Scope struct {
    75  	Parent int32
    76  	Ranges []Range
    77  	Vars   []*Var
    78  }
    79  
    80  // A Range represents a half-open interval [Start, End).
    81  type Range struct {
    82  	Start, End int64
    83  }
    84  
    85  // This container is used by the PutFunc* variants below when
    86  // creating the DWARF subprogram DIE(s) for a function.
    87  type FnState struct {
    88  	Name          string
    89  	Info          Sym
    90  	Loc           Sym
    91  	Ranges        Sym
    92  	Absfn         Sym
    93  	StartPC       Sym
    94  	StartPos      src.Pos
    95  	Size          int64
    96  	External      bool
    97  	Scopes        []Scope
    98  	InlCalls      InlCalls
    99  	UseBASEntries bool
   100  
   101  	dictIndexToOffset []int64
   102  }
   103  
   104  func EnableLogging(doit bool) {
   105  	logDwarf = doit
   106  }
   107  
   108  // MergeRanges creates a new range list by merging the ranges from
   109  // its two arguments, then returns the new list.
   110  func MergeRanges(in1, in2 []Range) []Range {
   111  	out := make([]Range, 0, len(in1)+len(in2))
   112  	i, j := 0, 0
   113  	for {
   114  		var cur Range
   115  		if i < len(in2) && j < len(in1) {
   116  			if in2[i].Start < in1[j].Start {
   117  				cur = in2[i]
   118  				i++
   119  			} else {
   120  				cur = in1[j]
   121  				j++
   122  			}
   123  		} else if i < len(in2) {
   124  			cur = in2[i]
   125  			i++
   126  		} else if j < len(in1) {
   127  			cur = in1[j]
   128  			j++
   129  		} else {
   130  			break
   131  		}
   132  
   133  		if n := len(out); n > 0 && cur.Start <= out[n-1].End {
   134  			out[n-1].End = cur.End
   135  		} else {
   136  			out = append(out, cur)
   137  		}
   138  	}
   139  
   140  	return out
   141  }
   142  
   143  // UnifyRanges merges the ranges from 'c' into the list of ranges for 's'.
   144  func (s *Scope) UnifyRanges(c *Scope) {
   145  	s.Ranges = MergeRanges(s.Ranges, c.Ranges)
   146  }
   147  
   148  // AppendRange adds r to s, if r is non-empty.
   149  // If possible, it extends the last Range in s.Ranges; if not, it creates a new one.
   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  	// index into ctx.InlTree describing the call inlined here
   168  	InlIndex int
   169  
   170  	// Position of the inlined call site.
   171  	CallPos src.Pos
   172  
   173  	// Dwarf abstract subroutine symbol (really *obj.LSym).
   174  	AbsFunSym Sym
   175  
   176  	// Indices of child inlines within Calls array above.
   177  	Children []int
   178  
   179  	// entries in this list are PAUTO's created by the inliner to
   180  	// capture the promoted formals and locals of the inlined callee.
   181  	InlVars []*Var
   182  
   183  	// PC ranges for this inlined call.
   184  	Ranges []Range
   185  
   186  	// Root call (not a child of some other call).
   187  	Root bool
   188  }
   189  
   190  // A Context specifies how to add data to a Sym.
   191  type Context interface {
   192  	PtrSize() int
   193  	Size(s Sym) int64
   194  	AddInt(s Sym, size int, i int64)
   195  	AddBytes(s Sym, b []byte)
   196  	AddAddress(s Sym, t any, ofs int64)
   197  	AddCURelativeAddress(s Sym, t any, ofs int64)
   198  	AddSectionOffset(s Sym, size int, t any, ofs int64)
   199  	AddDWARFAddrSectionOffset(s Sym, t any, ofs int64)
   200  	AddIndirectTextRef(s Sym, t any)
   201  	CurrentOffset(s Sym) int64
   202  	RecordDclReference(from Sym, to Sym, dclIdx int, inlIndex int)
   203  	RecordChildDieOffsets(s Sym, vars []*Var, offsets []int32)
   204  	AddString(s Sym, v string)
   205  	Logf(format string, args ...any)
   206  }
   207  
   208  // AppendUleb128 appends v to b using DWARF's unsigned LEB128 encoding.
   209  func AppendUleb128(b []byte, v uint64) []byte {
   210  	for {
   211  		c := uint8(v & 0x7f)
   212  		v >>= 7
   213  		if v != 0 {
   214  			c |= 0x80
   215  		}
   216  		b = append(b, c)
   217  		if c&0x80 == 0 {
   218  			break
   219  		}
   220  	}
   221  	return b
   222  }
   223  
   224  // AppendSleb128 appends v to b using DWARF's signed LEB128 encoding.
   225  func AppendSleb128(b []byte, v int64) []byte {
   226  	for {
   227  		c := uint8(v & 0x7f)
   228  		s := uint8(v & 0x40)
   229  		v >>= 7
   230  		if (v != -1 || s == 0) && (v != 0 || s != 0) {
   231  			c |= 0x80
   232  		}
   233  		b = append(b, c)
   234  		if c&0x80 == 0 {
   235  			break
   236  		}
   237  	}
   238  	return b
   239  }
   240  
   241  // sevenbits contains all unsigned seven bit numbers, indexed by their value.
   242  var sevenbits = [...]byte{
   243  	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
   244  	0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
   245  	0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
   246  	0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
   247  	0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
   248  	0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
   249  	0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
   250  	0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
   251  }
   252  
   253  // sevenBitU returns the unsigned LEB128 encoding of v if v is seven bits and nil otherwise.
   254  // The contents of the returned slice must not be modified.
   255  func sevenBitU(v int64) []byte {
   256  	if uint64(v) < uint64(len(sevenbits)) {
   257  		return sevenbits[v : v+1]
   258  	}
   259  	return nil
   260  }
   261  
   262  // sevenBitS returns the signed LEB128 encoding of v if v is seven bits and nil otherwise.
   263  // The contents of the returned slice must not be modified.
   264  func sevenBitS(v int64) []byte {
   265  	if uint64(v) <= 63 {
   266  		return sevenbits[v : v+1]
   267  	}
   268  	if uint64(-v) <= 64 {
   269  		return sevenbits[128+v : 128+v+1]
   270  	}
   271  	return nil
   272  }
   273  
   274  // Uleb128put appends v to s using DWARF's unsigned LEB128 encoding.
   275  func Uleb128put(ctxt Context, s Sym, v int64) {
   276  	b := sevenBitU(v)
   277  	if b == nil {
   278  		var encbuf [20]byte
   279  		b = AppendUleb128(encbuf[:0], uint64(v))
   280  	}
   281  	ctxt.AddBytes(s, b)
   282  }
   283  
   284  // Sleb128put appends v to s using DWARF's signed LEB128 encoding.
   285  func Sleb128put(ctxt Context, s Sym, v int64) {
   286  	b := sevenBitS(v)
   287  	if b == nil {
   288  		var encbuf [20]byte
   289  		b = AppendSleb128(encbuf[:0], v)
   290  	}
   291  	ctxt.AddBytes(s, b)
   292  }
   293  
   294  /*
   295   * Defining Abbrevs. This is hardcoded on a per-platform basis (that is,
   296   * each platform will see a fixed abbrev table for all objects); the number
   297   * of abbrev entries is fairly small (compared to C++ objects).  The DWARF
   298   * spec places no restriction on the ordering of attributes in the
   299   * Abbrevs and DIEs, and we will always write them out in the order
   300   * of declaration in the abbrev.
   301   */
   302  type dwAttrForm struct {
   303  	attr uint16
   304  	form uint8
   305  }
   306  
   307  // Go-specific type attributes.
   308  const (
   309  	DW_AT_go_kind = 0x2900
   310  	DW_AT_go_key  = 0x2901
   311  	DW_AT_go_elem = 0x2902
   312  	// Attribute for DW_TAG_member of a struct type.
   313  	// Nonzero value indicates the struct field is an embedded field.
   314  	DW_AT_go_embedded_field = 0x2903
   315  	DW_AT_go_runtime_type   = 0x2904
   316  
   317  	DW_AT_go_package_name   = 0x2905 // Attribute for DW_TAG_compile_unit
   318  	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
   319  	DW_AT_go_closure_offset = 0x2907 // Attribute for DW_TAG_variable, offset in the closure struct where this captured variable resides
   320  
   321  	DW_AT_internal_location = 253 // params and locals; not emitted
   322  )
   323  
   324  // Index into the abbrevs table below.
   325  const (
   326  	DW_ABRV_NULL = iota
   327  	DW_ABRV_COMPUNIT
   328  	DW_ABRV_COMPUNIT_TEXTLESS
   329  	DW_ABRV_FUNCTION
   330  	DW_ABRV_WRAPPER
   331  	DW_ABRV_FUNCTION_ABSTRACT
   332  	DW_ABRV_FUNCTION_CONCRETE
   333  	DW_ABRV_WRAPPER_CONCRETE
   334  	DW_ABRV_INLINED_SUBROUTINE
   335  	DW_ABRV_INLINED_SUBROUTINE_RANGES
   336  	DW_ABRV_VARIABLE
   337  	DW_ABRV_INT_CONSTANT
   338  	DW_ABRV_LEXICAL_BLOCK_RANGES
   339  	DW_ABRV_LEXICAL_BLOCK_SIMPLE
   340  	DW_ABRV_STRUCTFIELD
   341  	DW_ABRV_FUNCTYPEPARAM
   342  	DW_ABRV_FUNCTYPEOUTPARAM
   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 // only for void*, no DW_AT_type attr to please gdb 6.
   354  	DW_ABRV_SLICETYPE
   355  	DW_ABRV_STRINGTYPE
   356  	DW_ABRV_STRUCTTYPE
   357  	DW_ABRV_TYPEDECL
   358  	DW_ABRV_DICT_INDEX
   359  	DW_ABRV_LINKER_TRAMPOLINE
   360  	DW_ABRV_PUTVAR_START
   361  )
   362  
   363  type dwAbbrev struct {
   364  	tag      uint8
   365  	children uint8
   366  	attr     []dwAttrForm
   367  }
   368  
   369  var abbrevsFinalized bool
   370  
   371  // expandPseudoForm takes an input DW_FORM_xxx value and translates it
   372  // into a version- and platform-appropriate concrete form. Existing
   373  // concrete/real DW_FORM values are left untouched. For the moment the
   374  // only platform-specific pseudo-form is DW_FORM_udata_pseudo, which
   375  // gets expanded to DW_FORM_data4 on Darwin and DW_FORM_udata
   376  // everywhere else. See issue #31459 for more context. Then we have a
   377  // pair of pseudo-forms for lo and hi PC attributes, which are
   378  // expanded differently depending on whether we're generating DWARF
   379  // version 4 or 5.
   380  func expandPseudoForm(form uint8) uint8 {
   381  	switch form {
   382  	case DW_FORM_udata_pseudo:
   383  		expandedForm := DW_FORM_udata
   384  		if buildcfg.GOOS == "darwin" || buildcfg.GOOS == "ios" {
   385  			expandedForm = DW_FORM_data4
   386  		}
   387  		return uint8(expandedForm)
   388  	case DW_FORM_lo_pc_pseudo:
   389  		if buildcfg.Experiment.Dwarf5 {
   390  			return DW_FORM_addrx
   391  		}
   392  		return DW_FORM_addr
   393  	case DW_FORM_hi_pc_pseudo:
   394  		if buildcfg.Experiment.Dwarf5 {
   395  			return DW_FORM_udata
   396  		}
   397  		return DW_FORM_addr
   398  	default:
   399  		return form
   400  	}
   401  }
   402  
   403  // Abbrevs returns the finalized abbrev array for the platform,
   404  // expanding any DW_FORM pseudo-ops to real values.
   405  func Abbrevs() []dwAbbrev {
   406  	if abbrevsFinalized {
   407  		return abbrevs
   408  	}
   409  	abbrevs = append(abbrevs, putvarAbbrevs...)
   410  	for i := 1; i < len(abbrevs); i++ {
   411  		for j := 0; j < len(abbrevs[i].attr); j++ {
   412  			abbrevs[i].attr[j].form = expandPseudoForm(abbrevs[i].attr[j].form)
   413  		}
   414  	}
   415  	if buildcfg.Experiment.Dwarf5 {
   416  		// Tack on a new DW_AT_addr_base attribute to the compunit DIE,
   417  		// which will point to the offset in the .debug_addr section
   418  		// containing entries for this comp unit (this attr gets
   419  		// fixed up in the linker).
   420  		for i := 1; i < len(abbrevs); i++ {
   421  			haveLo := false
   422  			for j := 0; j < len(abbrevs[i].attr); j++ {
   423  				if abbrevs[i].attr[j].attr == DW_AT_low_pc {
   424  					haveLo = true
   425  				}
   426  			}
   427  			if abbrevs[i].tag == DW_TAG_compile_unit && haveLo {
   428  				abbrevs[i].attr = append(abbrevs[i].attr,
   429  					dwAttrForm{DW_AT_addr_base, DW_FORM_sec_offset})
   430  			}
   431  		}
   432  	}
   433  
   434  	abbrevsFinalized = true
   435  	return abbrevs
   436  }
   437  
   438  // abbrevs is a raw table of abbrev entries; it needs to be post-processed
   439  // by the Abbrevs() function above prior to being consumed, to expand
   440  // the 'pseudo-form' entries below to real DWARF form values.
   441  
   442  var abbrevs = []dwAbbrev{
   443  	/* The mandatory DW_ABRV_NULL entry. */
   444  	{0, 0, []dwAttrForm{}},
   445  
   446  	/* COMPUNIT */
   447  	{
   448  		DW_TAG_compile_unit,
   449  		DW_CHILDREN_yes,
   450  		[]dwAttrForm{
   451  			{DW_AT_name, DW_FORM_string},
   452  			{DW_AT_language, DW_FORM_data1},
   453  			{DW_AT_stmt_list, DW_FORM_sec_offset},
   454  			{DW_AT_low_pc, DW_FORM_addr},
   455  			{DW_AT_ranges, DW_FORM_sec_offset},
   456  			{DW_AT_comp_dir, DW_FORM_string},
   457  			{DW_AT_producer, DW_FORM_string},
   458  			{DW_AT_go_package_name, DW_FORM_string},
   459  			// NB: DWARF5 adds DW_AT_addr_base here.
   460  		},
   461  	},
   462  
   463  	/* COMPUNIT_TEXTLESS */
   464  	{
   465  		DW_TAG_compile_unit,
   466  		DW_CHILDREN_yes,
   467  		[]dwAttrForm{
   468  			{DW_AT_name, DW_FORM_string},
   469  			{DW_AT_language, DW_FORM_data1},
   470  			{DW_AT_comp_dir, DW_FORM_string},
   471  			{DW_AT_producer, DW_FORM_string},
   472  			{DW_AT_go_package_name, DW_FORM_string},
   473  		},
   474  	},
   475  
   476  	/* FUNCTION */
   477  	{
   478  		DW_TAG_subprogram,
   479  		DW_CHILDREN_yes,
   480  		[]dwAttrForm{
   481  			{DW_AT_name, DW_FORM_string},
   482  			{DW_AT_low_pc, DW_FORM_lo_pc_pseudo},
   483  			{DW_AT_high_pc, DW_FORM_hi_pc_pseudo},
   484  			{DW_AT_frame_base, DW_FORM_block1},
   485  			{DW_AT_decl_file, DW_FORM_data4},
   486  			{DW_AT_decl_line, DW_FORM_udata},
   487  			{DW_AT_external, DW_FORM_flag},
   488  		},
   489  	},
   490  
   491  	/* WRAPPER */
   492  	{
   493  		DW_TAG_subprogram,
   494  		DW_CHILDREN_yes,
   495  		[]dwAttrForm{
   496  			{DW_AT_name, DW_FORM_string},
   497  			{DW_AT_low_pc, DW_FORM_lo_pc_pseudo},
   498  			{DW_AT_high_pc, DW_FORM_hi_pc_pseudo},
   499  			{DW_AT_frame_base, DW_FORM_block1},
   500  			{DW_AT_trampoline, DW_FORM_flag},
   501  		},
   502  	},
   503  
   504  	/* FUNCTION_ABSTRACT */
   505  	{
   506  		DW_TAG_subprogram,
   507  		DW_CHILDREN_yes,
   508  		[]dwAttrForm{
   509  			{DW_AT_name, DW_FORM_string},
   510  			{DW_AT_inline, DW_FORM_data1},
   511  			{DW_AT_decl_line, DW_FORM_udata},
   512  			{DW_AT_external, DW_FORM_flag},
   513  		},
   514  	},
   515  
   516  	/* FUNCTION_CONCRETE */
   517  	{
   518  		DW_TAG_subprogram,
   519  		DW_CHILDREN_yes,
   520  		[]dwAttrForm{
   521  			{DW_AT_abstract_origin, DW_FORM_ref_addr},
   522  			{DW_AT_low_pc, DW_FORM_lo_pc_pseudo},
   523  			{DW_AT_high_pc, DW_FORM_hi_pc_pseudo},
   524  			{DW_AT_frame_base, DW_FORM_block1},
   525  		},
   526  	},
   527  
   528  	/* WRAPPER_CONCRETE */
   529  	{
   530  		DW_TAG_subprogram,
   531  		DW_CHILDREN_yes,
   532  		[]dwAttrForm{
   533  			{DW_AT_abstract_origin, DW_FORM_ref_addr},
   534  			{DW_AT_low_pc, DW_FORM_lo_pc_pseudo},
   535  			{DW_AT_high_pc, DW_FORM_hi_pc_pseudo},
   536  			{DW_AT_frame_base, DW_FORM_block1},
   537  			{DW_AT_trampoline, DW_FORM_flag},
   538  		},
   539  	},
   540  
   541  	/* INLINED_SUBROUTINE */
   542  	{
   543  		DW_TAG_inlined_subroutine,
   544  		DW_CHILDREN_yes,
   545  		[]dwAttrForm{
   546  			{DW_AT_abstract_origin, DW_FORM_ref_addr},
   547  			{DW_AT_low_pc, DW_FORM_lo_pc_pseudo},
   548  			{DW_AT_high_pc, DW_FORM_hi_pc_pseudo},
   549  			{DW_AT_call_file, DW_FORM_data4},
   550  			{DW_AT_call_line, DW_FORM_udata_pseudo}, // pseudo-form
   551  		},
   552  	},
   553  
   554  	/* INLINED_SUBROUTINE_RANGES */
   555  	{
   556  		DW_TAG_inlined_subroutine,
   557  		DW_CHILDREN_yes,
   558  		[]dwAttrForm{
   559  			{DW_AT_abstract_origin, DW_FORM_ref_addr},
   560  			{DW_AT_ranges, DW_FORM_sec_offset},
   561  			{DW_AT_call_file, DW_FORM_data4},
   562  			{DW_AT_call_line, DW_FORM_udata_pseudo}, // pseudo-form
   563  		},
   564  	},
   565  
   566  	/* VARIABLE */
   567  	{
   568  		DW_TAG_variable,
   569  		DW_CHILDREN_no,
   570  		[]dwAttrForm{
   571  			{DW_AT_name, DW_FORM_string},
   572  			{DW_AT_location, DW_FORM_block1},
   573  			{DW_AT_type, DW_FORM_ref_addr},
   574  			{DW_AT_external, DW_FORM_flag},
   575  		},
   576  	},
   577  
   578  	/* INT CONSTANT */
   579  	{
   580  		DW_TAG_constant,
   581  		DW_CHILDREN_no,
   582  		[]dwAttrForm{
   583  			{DW_AT_name, DW_FORM_string},
   584  			{DW_AT_type, DW_FORM_ref_addr},
   585  			{DW_AT_const_value, DW_FORM_sdata},
   586  		},
   587  	},
   588  
   589  	/* LEXICAL_BLOCK_RANGES */
   590  	{
   591  		DW_TAG_lexical_block,
   592  		DW_CHILDREN_yes,
   593  		[]dwAttrForm{
   594  			{DW_AT_ranges, DW_FORM_sec_offset},
   595  		},
   596  	},
   597  
   598  	/* LEXICAL_BLOCK_SIMPLE */
   599  	{
   600  		DW_TAG_lexical_block,
   601  		DW_CHILDREN_yes,
   602  		[]dwAttrForm{
   603  			// Note: unused if we are generating DWARF 5, we
   604  			// use the ranges form even if there is a singleton range.
   605  			{DW_AT_low_pc, DW_FORM_addr},
   606  			{DW_AT_high_pc, DW_FORM_addr},
   607  		},
   608  	},
   609  
   610  	/* STRUCTFIELD */
   611  	{
   612  		DW_TAG_member,
   613  		DW_CHILDREN_no,
   614  		// This abbrev is special-cased by the linker (unlike other DIEs
   615  		// we don't want a loader.Sym created for this DIE).
   616  		[]dwAttrForm{
   617  			{DW_AT_name, DW_FORM_string},
   618  			{DW_AT_data_member_location, DW_FORM_udata},
   619  			{DW_AT_type, DW_FORM_ref_addr},
   620  			{DW_AT_go_embedded_field, DW_FORM_flag},
   621  		},
   622  	},
   623  
   624  	/* FUNCTYPEPARAM */
   625  	{
   626  		DW_TAG_formal_parameter,
   627  		DW_CHILDREN_no,
   628  
   629  		// No name!
   630  		// This abbrev is special-cased by the linker (unlike other DIEs
   631  		// we don't want a loader.Sym created for this DIE).
   632  		[]dwAttrForm{
   633  			{DW_AT_type, DW_FORM_ref_addr},
   634  		},
   635  	},
   636  
   637  	/* FUNCTYPEOUTPARAM */
   638  	{
   639  		DW_TAG_formal_parameter,
   640  		DW_CHILDREN_no,
   641  
   642  		// No name!
   643  		// This abbrev is special-cased by the linker (unlike other DIEs
   644  		// we don't want a loader.Sym created for this DIE).
   645  		[]dwAttrForm{
   646  			{DW_AT_variable_parameter, DW_FORM_flag},
   647  			{DW_AT_type, DW_FORM_ref_addr},
   648  		},
   649  	},
   650  
   651  	/* DOTDOTDOT */
   652  	{
   653  		DW_TAG_unspecified_parameters,
   654  		DW_CHILDREN_no,
   655  		// No name.
   656  		// This abbrev is special-cased by the linker (unlike other DIEs
   657  		// we don't want a loader.Sym created for this DIE).
   658  		[]dwAttrForm{},
   659  	},
   660  
   661  	/* ARRAYRANGE */
   662  	{
   663  		DW_TAG_subrange_type,
   664  		DW_CHILDREN_no,
   665  
   666  		// No name!
   667  		// This abbrev is special-cased by the linker (unlike other DIEs
   668  		// we don't want a loader.Sym created for this DIE).
   669  		[]dwAttrForm{
   670  			{DW_AT_type, DW_FORM_ref_addr},
   671  			{DW_AT_count, DW_FORM_udata},
   672  		},
   673  	},
   674  
   675  	// Below here are the types considered public by ispubtype
   676  	/* NULLTYPE */
   677  	{
   678  		DW_TAG_unspecified_type,
   679  		DW_CHILDREN_no,
   680  		[]dwAttrForm{
   681  			{DW_AT_name, DW_FORM_string},
   682  		},
   683  	},
   684  
   685  	/* BASETYPE */
   686  	{
   687  		DW_TAG_base_type,
   688  		DW_CHILDREN_no,
   689  		[]dwAttrForm{
   690  			{DW_AT_name, DW_FORM_string},
   691  			{DW_AT_encoding, DW_FORM_data1},
   692  			{DW_AT_byte_size, DW_FORM_data1},
   693  			{DW_AT_go_kind, DW_FORM_data1},
   694  			{DW_AT_go_runtime_type, DW_FORM_addr},
   695  		},
   696  	},
   697  
   698  	/* ARRAYTYPE */
   699  	// child is subrange with upper bound
   700  	{
   701  		DW_TAG_array_type,
   702  		DW_CHILDREN_yes,
   703  		[]dwAttrForm{
   704  			{DW_AT_name, DW_FORM_string},
   705  			{DW_AT_type, DW_FORM_ref_addr},
   706  			{DW_AT_byte_size, DW_FORM_udata},
   707  			{DW_AT_go_kind, DW_FORM_data1},
   708  			{DW_AT_go_runtime_type, DW_FORM_addr},
   709  		},
   710  	},
   711  
   712  	/* CHANTYPE */
   713  	{
   714  		DW_TAG_typedef,
   715  		DW_CHILDREN_no,
   716  		[]dwAttrForm{
   717  			{DW_AT_name, DW_FORM_string},
   718  			{DW_AT_type, DW_FORM_ref_addr},
   719  			{DW_AT_go_kind, DW_FORM_data1},
   720  			{DW_AT_go_runtime_type, DW_FORM_addr},
   721  			{DW_AT_go_elem, DW_FORM_ref_addr},
   722  		},
   723  	},
   724  
   725  	/* FUNCTYPE */
   726  	{
   727  		DW_TAG_subroutine_type,
   728  		DW_CHILDREN_yes,
   729  		[]dwAttrForm{
   730  			{DW_AT_name, DW_FORM_string},
   731  			{DW_AT_byte_size, DW_FORM_udata},
   732  			{DW_AT_go_kind, DW_FORM_data1},
   733  			{DW_AT_go_runtime_type, DW_FORM_addr},
   734  		},
   735  	},
   736  
   737  	/* IFACETYPE */
   738  	{
   739  		DW_TAG_typedef,
   740  		DW_CHILDREN_yes,
   741  		[]dwAttrForm{
   742  			{DW_AT_name, DW_FORM_string},
   743  			{DW_AT_type, DW_FORM_ref_addr},
   744  			{DW_AT_go_kind, DW_FORM_data1},
   745  			{DW_AT_go_runtime_type, DW_FORM_addr},
   746  		},
   747  	},
   748  
   749  	/* MAPTYPE */
   750  	{
   751  		DW_TAG_typedef,
   752  		DW_CHILDREN_no,
   753  		[]dwAttrForm{
   754  			{DW_AT_name, DW_FORM_string},
   755  			{DW_AT_type, DW_FORM_ref_addr},
   756  			{DW_AT_go_kind, DW_FORM_data1},
   757  			{DW_AT_go_runtime_type, DW_FORM_addr},
   758  			{DW_AT_go_key, DW_FORM_ref_addr},
   759  			{DW_AT_go_elem, DW_FORM_ref_addr},
   760  		},
   761  	},
   762  
   763  	/* PTRTYPE */
   764  	{
   765  		DW_TAG_pointer_type,
   766  		DW_CHILDREN_no,
   767  		[]dwAttrForm{
   768  			{DW_AT_name, DW_FORM_string},
   769  			{DW_AT_type, DW_FORM_ref_addr},
   770  			{DW_AT_go_kind, DW_FORM_data1},
   771  			{DW_AT_go_runtime_type, DW_FORM_addr},
   772  		},
   773  	},
   774  
   775  	/* BARE_PTRTYPE */
   776  	{
   777  		DW_TAG_pointer_type,
   778  		DW_CHILDREN_no,
   779  		[]dwAttrForm{
   780  			{DW_AT_name, DW_FORM_string},
   781  			{DW_AT_go_runtime_type, DW_FORM_addr},
   782  		},
   783  	},
   784  
   785  	/* SLICETYPE */
   786  	{
   787  		DW_TAG_structure_type,
   788  		DW_CHILDREN_yes,
   789  		[]dwAttrForm{
   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},
   794  			{DW_AT_go_elem, DW_FORM_ref_addr},
   795  		},
   796  	},
   797  
   798  	/* STRINGTYPE */
   799  	{
   800  		DW_TAG_structure_type,
   801  		DW_CHILDREN_yes,
   802  		[]dwAttrForm{
   803  			{DW_AT_name, DW_FORM_string},
   804  			{DW_AT_byte_size, DW_FORM_udata},
   805  			{DW_AT_go_kind, DW_FORM_data1},
   806  			{DW_AT_go_runtime_type, DW_FORM_addr},
   807  		},
   808  	},
   809  
   810  	/* STRUCTTYPE */
   811  	{
   812  		DW_TAG_structure_type,
   813  		DW_CHILDREN_yes,
   814  		[]dwAttrForm{
   815  			{DW_AT_name, DW_FORM_string},
   816  			{DW_AT_byte_size, DW_FORM_udata},
   817  			{DW_AT_go_kind, DW_FORM_data1},
   818  			{DW_AT_go_runtime_type, DW_FORM_addr},
   819  		},
   820  	},
   821  
   822  	/* TYPEDECL */
   823  	{
   824  		DW_TAG_typedef,
   825  		DW_CHILDREN_no,
   826  		[]dwAttrForm{
   827  			{DW_AT_name, DW_FORM_string},
   828  			{DW_AT_type, DW_FORM_ref_addr},
   829  		},
   830  	},
   831  
   832  	/* DICT_INDEX */
   833  	{
   834  		DW_TAG_typedef,
   835  		DW_CHILDREN_no,
   836  		[]dwAttrForm{
   837  			{DW_AT_name, DW_FORM_string},
   838  			{DW_AT_type, DW_FORM_ref_addr},
   839  			{DW_AT_go_dict_index, DW_FORM_udata},
   840  		},
   841  	},
   842  
   843  	// LINKER_TRAMPOLINE
   844  	// Use DW_FORM_addr for DW_AT_low_pc instead of DW_FORM_lo_pc_pseudo.
   845  	// A trampoline PC has one reference, so DW_FORM_addrx would add a
   846  	// .debug_addr entry without reducing output size.
   847  	{
   848  		DW_TAG_subprogram,
   849  		DW_CHILDREN_no,
   850  		[]dwAttrForm{
   851  			{DW_AT_low_pc, DW_FORM_addr},
   852  			{DW_AT_high_pc, DW_FORM_udata},
   853  			{DW_AT_trampoline, DW_FORM_addr},
   854  		},
   855  	},
   856  }
   857  
   858  // GetAbbrev returns the contents of the .debug_abbrev section.
   859  func GetAbbrev() []byte {
   860  	abbrevs := Abbrevs()
   861  	var buf []byte
   862  	for i := 1; i < len(abbrevs); i++ {
   863  		// See section 7.5.3
   864  		buf = AppendUleb128(buf, uint64(i))
   865  		buf = AppendUleb128(buf, uint64(abbrevs[i].tag))
   866  		buf = append(buf, abbrevs[i].children)
   867  		for _, f := range abbrevs[i].attr {
   868  			buf = AppendUleb128(buf, uint64(f.attr))
   869  			buf = AppendUleb128(buf, uint64(f.form))
   870  		}
   871  		buf = append(buf, 0, 0)
   872  	}
   873  	return append(buf, 0)
   874  }
   875  
   876  /*
   877   * Debugging Information Entries and their attributes.
   878   */
   879  
   880  // DWAttr represents an attribute of a DWDie.
   881  //
   882  // For DW_CLS_string and _block, value should contain the length, and
   883  // data the data, for _reference, value is 0 and data is a DWDie* to
   884  // the referenced instance, for all others, value is the whole thing
   885  // and data is null.
   886  type DWAttr struct {
   887  	Link  *DWAttr
   888  	Atr   uint16 // DW_AT_
   889  	Cls   uint8  // DW_CLS_
   890  	Value int64
   891  	Data  any
   892  }
   893  
   894  // DWDie represents a DWARF debug info entry.
   895  type DWDie struct {
   896  	Abbrev int
   897  	Link   *DWDie
   898  	Child  *DWDie
   899  	Attr   *DWAttr
   900  	Sym    Sym
   901  }
   902  
   903  func putattr(ctxt Context, s Sym, abbrev int, form int, cls int, value int64, data any) error {
   904  	switch form {
   905  	case DW_FORM_addr: // address
   906  		// Allow nil addresses for DW_AT_go_runtime_type.
   907  		if data == nil && value == 0 {
   908  			ctxt.AddInt(s, ctxt.PtrSize(), 0)
   909  			break
   910  		}
   911  		if cls == DW_CLS_GO_TYPEREF {
   912  			ctxt.AddSectionOffset(s, ctxt.PtrSize(), data, value)
   913  			break
   914  		}
   915  		ctxt.AddAddress(s, data, value)
   916  
   917  	case DW_FORM_block1: // block
   918  		if cls == DW_CLS_ADDRESS {
   919  			ctxt.AddInt(s, 1, int64(1+ctxt.PtrSize()))
   920  			ctxt.AddInt(s, 1, DW_OP_addr)
   921  			ctxt.AddAddress(s, data, 0)
   922  			break
   923  		}
   924  
   925  		value &= 0xff
   926  		ctxt.AddInt(s, 1, value)
   927  		p := data.([]byte)[:value]
   928  		ctxt.AddBytes(s, p)
   929  
   930  	case DW_FORM_block2: // block
   931  		value &= 0xffff
   932  
   933  		ctxt.AddInt(s, 2, value)
   934  		p := data.([]byte)[:value]
   935  		ctxt.AddBytes(s, p)
   936  
   937  	case DW_FORM_block4: // block
   938  		value &= 0xffffffff
   939  
   940  		ctxt.AddInt(s, 4, value)
   941  		p := data.([]byte)[:value]
   942  		ctxt.AddBytes(s, p)
   943  
   944  	case DW_FORM_block: // block
   945  		Uleb128put(ctxt, s, value)
   946  
   947  		p := data.([]byte)[:value]
   948  		ctxt.AddBytes(s, p)
   949  
   950  	case DW_FORM_data1: // constant
   951  		ctxt.AddInt(s, 1, value)
   952  
   953  	case DW_FORM_data2: // constant
   954  		ctxt.AddInt(s, 2, value)
   955  
   956  	case DW_FORM_data4: // constant, {line,loclist,mac,rangelist}ptr
   957  		if cls == DW_CLS_PTR { // DW_AT_stmt_list and DW_AT_ranges
   958  			ctxt.AddDWARFAddrSectionOffset(s, data, value)
   959  			break
   960  		}
   961  		ctxt.AddInt(s, 4, value)
   962  
   963  	case DW_FORM_data8: // constant, {line,loclist,mac,rangelist}ptr
   964  		ctxt.AddInt(s, 8, value)
   965  
   966  	case DW_FORM_sdata: // constant
   967  		Sleb128put(ctxt, s, value)
   968  
   969  	case DW_FORM_udata: // constant
   970  		Uleb128put(ctxt, s, value)
   971  
   972  	case DW_FORM_string: // string
   973  		str := data.(string)
   974  		ctxt.AddString(s, str)
   975  		// TODO(ribrdb): verify padded strings are never used and remove this
   976  		for i := int64(len(str)); i < value; i++ {
   977  			ctxt.AddInt(s, 1, 0)
   978  		}
   979  
   980  	case DW_FORM_flag: // flag
   981  		if value != 0 {
   982  			ctxt.AddInt(s, 1, 1)
   983  		} else {
   984  			ctxt.AddInt(s, 1, 0)
   985  		}
   986  
   987  	// As of DWARF 3 the ref_addr is always 32 bits, unless emitting a large
   988  	// (> 4 GB of debug info aka "64-bit") unit, which we don't implement.
   989  	case DW_FORM_ref_addr: // reference to a DIE in the .info section
   990  		fallthrough
   991  	case DW_FORM_sec_offset: // offset into a DWARF section other than .info
   992  		if data == nil {
   993  			return fmt.Errorf("dwarf: null reference in %d", abbrev)
   994  		}
   995  		ctxt.AddDWARFAddrSectionOffset(s, data, value)
   996  
   997  	case DW_FORM_addrx: // index into .debug_addr section
   998  		ctxt.AddIndirectTextRef(s, data)
   999  
  1000  	case DW_FORM_ref1, // reference within the compilation unit
  1001  		DW_FORM_ref2,      // reference
  1002  		DW_FORM_ref4,      // reference
  1003  		DW_FORM_ref8,      // reference
  1004  		DW_FORM_ref_udata, // reference
  1005  
  1006  		DW_FORM_strp,     // string
  1007  		DW_FORM_indirect: // (see Section 7.5.3)
  1008  		fallthrough
  1009  	default:
  1010  		return fmt.Errorf("dwarf: unsupported attribute form %d / class %d", form, cls)
  1011  	}
  1012  	return nil
  1013  }
  1014  
  1015  // PutAttrs writes the attributes for a DIE to symbol 's'.
  1016  //
  1017  // Note that we can (and do) add arbitrary attributes to a DIE, but
  1018  // only the ones actually listed in the Abbrev will be written out.
  1019  func PutAttrs(ctxt Context, s Sym, abbrev int, attr *DWAttr) {
  1020  	abbrevs := Abbrevs()
  1021  Outer:
  1022  	for _, f := range abbrevs[abbrev].attr {
  1023  		for ap := attr; ap != nil; ap = ap.Link {
  1024  			if ap.Atr == f.attr {
  1025  				putattr(ctxt, s, abbrev, int(f.form), int(ap.Cls), ap.Value, ap.Data)
  1026  				continue Outer
  1027  			}
  1028  		}
  1029  
  1030  		putattr(ctxt, s, abbrev, int(f.form), 0, 0, nil)
  1031  	}
  1032  }
  1033  
  1034  // HasChildren reports whether 'die' uses an abbrev that supports children.
  1035  func HasChildren(die *DWDie) bool {
  1036  	abbrevs := Abbrevs()
  1037  	return abbrevs[die.Abbrev].children != 0
  1038  }
  1039  
  1040  // PutIntConst writes a DIE for an integer constant
  1041  func PutIntConst(ctxt Context, info, typ Sym, name string, val int64) {
  1042  	Uleb128put(ctxt, info, DW_ABRV_INT_CONSTANT)
  1043  	putattr(ctxt, info, DW_ABRV_INT_CONSTANT, DW_FORM_string, DW_CLS_STRING, int64(len(name)), name)
  1044  	putattr(ctxt, info, DW_ABRV_INT_CONSTANT, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, typ)
  1045  	putattr(ctxt, info, DW_ABRV_INT_CONSTANT, DW_FORM_sdata, DW_CLS_CONSTANT, val, nil)
  1046  }
  1047  
  1048  // PutGlobal writes a DIE for a global variable.
  1049  func PutGlobal(ctxt Context, info, typ, gvar Sym, name string) {
  1050  	Uleb128put(ctxt, info, DW_ABRV_VARIABLE)
  1051  	putattr(ctxt, info, DW_ABRV_VARIABLE, DW_FORM_string, DW_CLS_STRING, int64(len(name)), name)
  1052  	putattr(ctxt, info, DW_ABRV_VARIABLE, DW_FORM_block1, DW_CLS_ADDRESS, 0, gvar)
  1053  	putattr(ctxt, info, DW_ABRV_VARIABLE, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, typ)
  1054  	putattr(ctxt, info, DW_ABRV_VARIABLE, DW_FORM_flag, DW_CLS_FLAG, 1, nil)
  1055  }
  1056  
  1057  // PutBasedRanges writes a range table to sym. All addresses in ranges are
  1058  // relative to some base address, which must be arranged by the caller
  1059  // (e.g., with a DW_AT_low_pc attribute, or in a BASE-prefixed range).
  1060  func PutBasedRanges(ctxt Context, sym Sym, ranges []Range) {
  1061  	ps := ctxt.PtrSize()
  1062  	// Write ranges.
  1063  	for _, r := range ranges {
  1064  		ctxt.AddInt(sym, ps, r.Start)
  1065  		ctxt.AddInt(sym, ps, r.End)
  1066  	}
  1067  	// Write trailer.
  1068  	ctxt.AddInt(sym, ps, 0)
  1069  	ctxt.AddInt(sym, ps, 0)
  1070  }
  1071  
  1072  // PutRngListRanges writes a DWARF5-style set of rangelist entries to sym,
  1073  // using base as a starting/base address.
  1074  func PutRngListRanges(ctxt Context, sym Sym, base Sym, ranges []Range) {
  1075  	addULEB128 := func(v int64) {
  1076  		b := sevenBitU(v)
  1077  		if b == nil {
  1078  			var encbuf [20]byte
  1079  			b = AppendUleb128(encbuf[:0], uint64(v))
  1080  		}
  1081  		ctxt.AddBytes(sym, b)
  1082  	}
  1083  	// First entry is base address.
  1084  	ctxt.AddInt(sym, 1, DW_RLE_base_addressx)
  1085  	ctxt.AddIndirectTextRef(sym, base)
  1086  	// Remaining entries are .debug_rnglist offset pairs
  1087  	for _, r := range ranges {
  1088  		ctxt.AddInt(sym, 1, DW_RLE_offset_pair)
  1089  		addULEB128(r.Start)
  1090  		addULEB128(r.End)
  1091  	}
  1092  	// Terminator to mark end of list
  1093  	ctxt.AddInt(sym, 1, DW_RLE_end_of_list)
  1094  }
  1095  
  1096  // PutRanges writes a range table to s.Ranges.
  1097  // All addresses in ranges are relative to s.base.
  1098  func (s *FnState) PutRanges(ctxt Context, ranges []Range) {
  1099  	ps := ctxt.PtrSize()
  1100  	sym, base := s.Ranges, s.StartPC
  1101  
  1102  	if buildcfg.Experiment.Dwarf5 {
  1103  		PutRngListRanges(ctxt, sym, base, ranges)
  1104  		return
  1105  	}
  1106  
  1107  	if s.UseBASEntries {
  1108  		// Using a Base Address Selection Entry reduces the number of relocations, but
  1109  		// this is not done on macOS because it is not supported by dsymutil/dwarfdump/lldb
  1110  		ctxt.AddInt(sym, ps, -1)
  1111  		ctxt.AddAddress(sym, base, 0)
  1112  		PutBasedRanges(ctxt, sym, ranges)
  1113  		return
  1114  	}
  1115  
  1116  	// Write ranges full of relocations
  1117  	for _, r := range ranges {
  1118  		ctxt.AddCURelativeAddress(sym, base, r.Start)
  1119  		ctxt.AddCURelativeAddress(sym, base, r.End)
  1120  	}
  1121  	// Write trailer.
  1122  	ctxt.AddInt(sym, ps, 0)
  1123  	ctxt.AddInt(sym, ps, 0)
  1124  }
  1125  
  1126  // Return TRUE if the inlined call in the specified slot is empty,
  1127  // meaning it has a zero-length range (no instructions), and all
  1128  // of its children are empty.
  1129  func isEmptyInlinedCall(slot int, calls *InlCalls) bool {
  1130  	ic := &calls.Calls[slot]
  1131  	if ic.InlIndex == -2 {
  1132  		return true
  1133  	}
  1134  	live := false
  1135  	for _, k := range ic.Children {
  1136  		if !isEmptyInlinedCall(k, calls) {
  1137  			live = true
  1138  		}
  1139  	}
  1140  	if len(ic.Ranges) > 0 {
  1141  		live = true
  1142  	}
  1143  	if !live {
  1144  		ic.InlIndex = -2
  1145  	}
  1146  	return !live
  1147  }
  1148  
  1149  // Slot -1:    return top-level inlines.
  1150  // Slot >= 0:  return children of that slot.
  1151  func inlChildren(slot int, calls *InlCalls) []int {
  1152  	var kids []int
  1153  	if slot != -1 {
  1154  		for _, k := range calls.Calls[slot].Children {
  1155  			if !isEmptyInlinedCall(k, calls) {
  1156  				kids = append(kids, k)
  1157  			}
  1158  		}
  1159  	} else {
  1160  		for k := 0; k < len(calls.Calls); k += 1 {
  1161  			if calls.Calls[k].Root && !isEmptyInlinedCall(k, calls) {
  1162  				kids = append(kids, k)
  1163  			}
  1164  		}
  1165  	}
  1166  	return kids
  1167  }
  1168  
  1169  func inlinedVarTable(inlcalls *InlCalls) map[*Var]bool {
  1170  	vars := make(map[*Var]bool)
  1171  	for _, ic := range inlcalls.Calls {
  1172  		for _, v := range ic.InlVars {
  1173  			vars[v] = true
  1174  		}
  1175  	}
  1176  	return vars
  1177  }
  1178  
  1179  // The s.Scopes slice contains variables were originally part of the
  1180  // function being emitted, as well as variables that were imported
  1181  // from various callee functions during the inlining process. This
  1182  // function prunes out any variables from the latter category (since
  1183  // they will be emitted as part of DWARF inlined_subroutine DIEs) and
  1184  // then generates scopes for vars in the former category.
  1185  func putPrunedScopes(ctxt Context, s *FnState, fnabbrev int) error {
  1186  	if len(s.Scopes) == 0 {
  1187  		return nil
  1188  	}
  1189  	scopes := make([]Scope, len(s.Scopes), len(s.Scopes))
  1190  	pvars := inlinedVarTable(&s.InlCalls)
  1191  	for k, s := range s.Scopes {
  1192  		var pruned Scope = Scope{Parent: s.Parent, Ranges: s.Ranges}
  1193  		for i := 0; i < len(s.Vars); i++ {
  1194  			_, found := pvars[s.Vars[i]]
  1195  			if !found {
  1196  				pruned.Vars = append(pruned.Vars, s.Vars[i])
  1197  			}
  1198  		}
  1199  		slices.SortFunc(pruned.Vars, byChildIndexCmp)
  1200  		scopes[k] = pruned
  1201  	}
  1202  
  1203  	s.dictIndexToOffset = putparamtypes(ctxt, s, scopes, fnabbrev)
  1204  
  1205  	var encbuf [20]byte
  1206  	if putscope(ctxt, s, scopes, 0, fnabbrev, encbuf[:0]) < int32(len(scopes)) {
  1207  		return errors.New("multiple toplevel scopes")
  1208  	}
  1209  	return nil
  1210  }
  1211  
  1212  // Emit DWARF attributes and child DIEs for an 'abstract' subprogram.
  1213  // The abstract subprogram DIE for a function contains its
  1214  // location-independent attributes (name, type, etc). Other instances
  1215  // of the function (any inlined copy of it, or the single out-of-line
  1216  // 'concrete' instance) will contain a pointer back to this abstract
  1217  // DIE (as a space-saving measure, so that name/type etc doesn't have
  1218  // to be repeated for each inlined copy).
  1219  func PutAbstractFunc(ctxt Context, s *FnState) error {
  1220  	if logDwarf {
  1221  		ctxt.Logf("PutAbstractFunc(%v)\n", s.Absfn)
  1222  	}
  1223  
  1224  	abbrev := DW_ABRV_FUNCTION_ABSTRACT
  1225  	Uleb128put(ctxt, s.Absfn, int64(abbrev))
  1226  
  1227  	fullname := s.Name
  1228  	if strings.HasPrefix(s.Name, `"".`) {
  1229  		return fmt.Errorf("unqualified symbol name: %v", s.Name)
  1230  	}
  1231  	putattr(ctxt, s.Absfn, abbrev, DW_FORM_string, DW_CLS_STRING, int64(len(fullname)), fullname)
  1232  
  1233  	// DW_AT_inlined value
  1234  	putattr(ctxt, s.Absfn, abbrev, DW_FORM_data1, DW_CLS_CONSTANT, int64(DW_INL_inlined), nil)
  1235  
  1236  	// TODO(mdempsky): Shouldn't we write out StartPos.FileIndex() too?
  1237  	putattr(ctxt, s.Absfn, abbrev, DW_FORM_udata, DW_CLS_CONSTANT, int64(s.StartPos.RelLine()), nil)
  1238  
  1239  	var ev int64
  1240  	if s.External {
  1241  		ev = 1
  1242  	}
  1243  	putattr(ctxt, s.Absfn, abbrev, DW_FORM_flag, DW_CLS_FLAG, ev, 0)
  1244  
  1245  	// Child variables (may be empty)
  1246  	var flattened []*Var
  1247  
  1248  	// This slice will hold the offset in bytes for each child var DIE
  1249  	// with respect to the start of the parent subprogram DIE.
  1250  	var offsets []int32
  1251  
  1252  	// Scopes/vars
  1253  	if len(s.Scopes) > 0 {
  1254  		// For abstract subprogram DIEs we want to flatten out scope info:
  1255  		// lexical scope DIEs contain range and/or hi/lo PC attributes,
  1256  		// which we explicitly don't want for the abstract subprogram DIE.
  1257  		pvars := inlinedVarTable(&s.InlCalls)
  1258  		for _, scope := range s.Scopes {
  1259  			for i := 0; i < len(scope.Vars); i++ {
  1260  				_, found := pvars[scope.Vars[i]]
  1261  				if found || !scope.Vars[i].IsInAbstract {
  1262  					continue
  1263  				}
  1264  				flattened = append(flattened, scope.Vars[i])
  1265  			}
  1266  		}
  1267  		if len(flattened) > 0 {
  1268  			slices.SortFunc(flattened, byChildIndexCmp)
  1269  
  1270  			if logDwarf {
  1271  				ctxt.Logf("putAbstractScope(%v): vars:", s.Info)
  1272  				for i, v := range flattened {
  1273  					ctxt.Logf(" %d:%s", i, v.Name)
  1274  				}
  1275  				ctxt.Logf("\n")
  1276  			}
  1277  
  1278  			// This slice will hold the offset in bytes for each child
  1279  			// variable DIE with respect to the start of the parent
  1280  			// subprogram DIE.
  1281  			for _, v := range flattened {
  1282  				offsets = append(offsets, int32(ctxt.CurrentOffset(s.Absfn)))
  1283  				putAbstractVar(ctxt, s.Absfn, v)
  1284  			}
  1285  		}
  1286  	}
  1287  	ctxt.RecordChildDieOffsets(s.Absfn, flattened, offsets)
  1288  
  1289  	Uleb128put(ctxt, s.Absfn, 0)
  1290  	return nil
  1291  }
  1292  
  1293  // dwarfFileIndex returns the DWARF file index value for the file associated
  1294  // with pos.
  1295  func dwarfFileIndex(pos src.Pos) int64 {
  1296  	return int64(1 + pos.FileIndex())
  1297  }
  1298  
  1299  // Emit DWARF attributes and child DIEs for an inlined subroutine. The
  1300  // first attribute of an inlined subroutine DIE is a reference back to
  1301  // its corresponding 'abstract' DIE (containing location-independent
  1302  // attributes such as name, type, etc). Inlined subroutine DIEs can
  1303  // have other inlined subroutine DIEs as children.
  1304  func putInlinedFunc(ctxt Context, s *FnState, callIdx int) error {
  1305  	ic := s.InlCalls.Calls[callIdx]
  1306  	callee := ic.AbsFunSym
  1307  
  1308  	// For DWARF 5, we always use the ranges form of the abbrev, since
  1309  	// it is more compact than using explicit hi/lo PC attrs.  See
  1310  	// issue #72821 for more on why this makes sense.
  1311  	abbrev := DW_ABRV_INLINED_SUBROUTINE_RANGES
  1312  	if len(ic.Ranges) == 1 && !buildcfg.Experiment.Dwarf5 {
  1313  		abbrev = DW_ABRV_INLINED_SUBROUTINE
  1314  	}
  1315  	Uleb128put(ctxt, s.Info, int64(abbrev))
  1316  
  1317  	if logDwarf {
  1318  		ctxt.Logf("putInlinedFunc(callee=%v,abbrev=%d)\n", callee, abbrev)
  1319  	}
  1320  
  1321  	// Abstract origin.
  1322  	putattr(ctxt, s.Info, abbrev, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, callee)
  1323  
  1324  	if abbrev == DW_ABRV_INLINED_SUBROUTINE_RANGES {
  1325  		putattr(ctxt, s.Info, abbrev, DW_FORM_sec_offset, DW_CLS_PTR, ctxt.Size(s.Ranges), s.Ranges)
  1326  		s.PutRanges(ctxt, ic.Ranges)
  1327  	} else {
  1328  		st := ic.Ranges[0].Start
  1329  		en := ic.Ranges[0].End
  1330  		emitHiLoPc(ctxt, abbrev, s, st, en)
  1331  	}
  1332  
  1333  	// Emit call file, line attrs.
  1334  	putattr(ctxt, s.Info, abbrev, DW_FORM_data4, DW_CLS_CONSTANT, dwarfFileIndex(ic.CallPos), nil)
  1335  	form := int(expandPseudoForm(DW_FORM_udata_pseudo))
  1336  	putattr(ctxt, s.Info, abbrev, form, DW_CLS_CONSTANT, int64(ic.CallPos.RelLine()), nil)
  1337  
  1338  	// Variables associated with this inlined routine instance.
  1339  	vars := ic.InlVars
  1340  	slices.SortFunc(vars, byChildIndexCmp)
  1341  	inlIndex := ic.InlIndex
  1342  	var encbuf [20]byte
  1343  	for _, v := range vars {
  1344  		if !v.IsInAbstract {
  1345  			continue
  1346  		}
  1347  		putvar(ctxt, s, v, callee, abbrev, inlIndex, encbuf[:0])
  1348  	}
  1349  
  1350  	// Children of this inline.
  1351  	for _, sib := range inlChildren(callIdx, &s.InlCalls) {
  1352  		err := putInlinedFunc(ctxt, s, sib)
  1353  		if err != nil {
  1354  			return err
  1355  		}
  1356  	}
  1357  
  1358  	Uleb128put(ctxt, s.Info, 0)
  1359  	return nil
  1360  }
  1361  
  1362  func emitHiLoPc(ctxt Context, abbrev int, fns *FnState, st int64, en int64) {
  1363  	if buildcfg.Experiment.Dwarf5 {
  1364  		putattr(ctxt, fns.Info, abbrev, DW_FORM_addrx, DW_CLS_CONSTANT, st, fns.StartPC)
  1365  		putattr(ctxt, fns.Info, abbrev, DW_FORM_udata, DW_CLS_CONSTANT, en, 0)
  1366  	} else {
  1367  		putattr(ctxt, fns.Info, abbrev, DW_FORM_addr, DW_CLS_ADDRESS, st, fns.StartPC)
  1368  		putattr(ctxt, fns.Info, abbrev, DW_FORM_addr, DW_CLS_ADDRESS, en, fns.StartPC)
  1369  	}
  1370  }
  1371  
  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, fncount int) error {
  1380  	if logDwarf {
  1381  		ctxt.Logf("PutConcreteFunc(%v)\n", s.Info)
  1382  	}
  1383  	abbrev := DW_ABRV_FUNCTION_CONCRETE
  1384  	if isWrapper {
  1385  		abbrev = DW_ABRV_WRAPPER_CONCRETE
  1386  	}
  1387  	Uleb128put(ctxt, s.Info, int64(abbrev))
  1388  
  1389  	// Abstract origin.
  1390  	putattr(ctxt, s.Info, abbrev, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, s.Absfn)
  1391  
  1392  	// Start/end PC.
  1393  	emitHiLoPc(ctxt, abbrev, s, 0, s.Size)
  1394  
  1395  	// cfa / frame base
  1396  	putattr(ctxt, s.Info, abbrev, DW_FORM_block1, DW_CLS_BLOCK, 1, []byte{DW_OP_call_frame_cfa})
  1397  
  1398  	if isWrapper {
  1399  		putattr(ctxt, s.Info, abbrev, DW_FORM_flag, DW_CLS_FLAG, int64(1), 0)
  1400  	}
  1401  
  1402  	// Scopes
  1403  	if err := putPrunedScopes(ctxt, s, abbrev); err != nil {
  1404  		return err
  1405  	}
  1406  
  1407  	// Inlined subroutines.
  1408  	for _, sib := range inlChildren(-1, &s.InlCalls) {
  1409  		err := putInlinedFunc(ctxt, s, sib)
  1410  		if err != nil {
  1411  			return err
  1412  		}
  1413  	}
  1414  
  1415  	Uleb128put(ctxt, s.Info, 0)
  1416  	return nil
  1417  }
  1418  
  1419  // Emit DWARF attributes and child DIEs for a subprogram. Here
  1420  // 'default' implies that the function in question was not inlined
  1421  // when its containing package was compiled (hence there is no need to
  1422  // emit an abstract version for it to use as a base for inlined
  1423  // routine records).
  1424  func PutDefaultFunc(ctxt Context, s *FnState, isWrapper bool) error {
  1425  	if logDwarf {
  1426  		ctxt.Logf("PutDefaultFunc(%v)\n", s.Info)
  1427  	}
  1428  	abbrev := DW_ABRV_FUNCTION
  1429  	if isWrapper {
  1430  		abbrev = DW_ABRV_WRAPPER
  1431  	}
  1432  	Uleb128put(ctxt, s.Info, int64(abbrev))
  1433  
  1434  	name := s.Name
  1435  	if strings.HasPrefix(name, `"".`) {
  1436  		return fmt.Errorf("unqualified symbol name: %v", name)
  1437  	}
  1438  
  1439  	putattr(ctxt, s.Info, DW_ABRV_FUNCTION, DW_FORM_string, DW_CLS_STRING, int64(len(name)), name)
  1440  	emitHiLoPc(ctxt, abbrev, s, 0, s.Size)
  1441  	putattr(ctxt, s.Info, abbrev, DW_FORM_block1, DW_CLS_BLOCK, 1, []byte{DW_OP_call_frame_cfa})
  1442  	if isWrapper {
  1443  		putattr(ctxt, s.Info, abbrev, DW_FORM_flag, DW_CLS_FLAG, int64(1), 0)
  1444  	} else {
  1445  		putattr(ctxt, s.Info, abbrev, DW_FORM_data4, DW_CLS_CONSTANT, dwarfFileIndex(s.StartPos), nil)
  1446  		putattr(ctxt, s.Info, abbrev, DW_FORM_udata, DW_CLS_CONSTANT, int64(s.StartPos.RelLine()), nil)
  1447  
  1448  		var ev int64
  1449  		if s.External {
  1450  			ev = 1
  1451  		}
  1452  		putattr(ctxt, s.Info, abbrev, DW_FORM_flag, DW_CLS_FLAG, ev, 0)
  1453  	}
  1454  
  1455  	// Scopes
  1456  	if err := putPrunedScopes(ctxt, s, abbrev); err != nil {
  1457  		return err
  1458  	}
  1459  
  1460  	// Inlined subroutines.
  1461  	for _, sib := range inlChildren(-1, &s.InlCalls) {
  1462  		err := putInlinedFunc(ctxt, s, sib)
  1463  		if err != nil {
  1464  			return err
  1465  		}
  1466  	}
  1467  
  1468  	Uleb128put(ctxt, s.Info, 0)
  1469  	return nil
  1470  }
  1471  
  1472  // putparamtypes writes typedef DIEs for any parametric types that are used by this function.
  1473  func putparamtypes(ctxt Context, s *FnState, scopes []Scope, fnabbrev int) []int64 {
  1474  	if fnabbrev == DW_ABRV_FUNCTION_CONCRETE {
  1475  		return nil
  1476  	}
  1477  
  1478  	maxDictIndex := uint16(0)
  1479  
  1480  	for i := range scopes {
  1481  		for _, v := range scopes[i].Vars {
  1482  			if v.DictIndex > maxDictIndex {
  1483  				maxDictIndex = v.DictIndex
  1484  			}
  1485  		}
  1486  	}
  1487  
  1488  	if maxDictIndex == 0 {
  1489  		return nil
  1490  	}
  1491  
  1492  	dictIndexToOffset := make([]int64, maxDictIndex)
  1493  
  1494  	for i := range scopes {
  1495  		for _, v := range scopes[i].Vars {
  1496  			if v.DictIndex == 0 || dictIndexToOffset[v.DictIndex-1] != 0 {
  1497  				continue
  1498  			}
  1499  
  1500  			dictIndexToOffset[v.DictIndex-1] = ctxt.CurrentOffset(s.Info)
  1501  
  1502  			Uleb128put(ctxt, s.Info, int64(DW_ABRV_DICT_INDEX))
  1503  			n := fmt.Sprintf(".param%d", v.DictIndex-1)
  1504  			putattr(ctxt, s.Info, DW_ABRV_DICT_INDEX, DW_FORM_string, DW_CLS_STRING, int64(len(n)), n)
  1505  			putattr(ctxt, s.Info, DW_ABRV_DICT_INDEX, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, v.Type)
  1506  			putattr(ctxt, s.Info, DW_ABRV_DICT_INDEX, DW_FORM_udata, DW_CLS_CONSTANT, int64(v.DictIndex-1), nil)
  1507  		}
  1508  	}
  1509  
  1510  	return dictIndexToOffset
  1511  }
  1512  
  1513  func putscope(ctxt Context, s *FnState, scopes []Scope, curscope int32, fnabbrev int, encbuf []byte) int32 {
  1514  
  1515  	if logDwarf {
  1516  		ctxt.Logf("putscope(%v,%d): vars:", s.Info, curscope)
  1517  		for i, v := range scopes[curscope].Vars {
  1518  			ctxt.Logf(" %d:%d:%s", i, v.ChildIndex, v.Name)
  1519  		}
  1520  		ctxt.Logf("\n")
  1521  	}
  1522  
  1523  	for _, v := range scopes[curscope].Vars {
  1524  		putvar(ctxt, s, v, s.Absfn, fnabbrev, -1, encbuf)
  1525  	}
  1526  	this := curscope
  1527  	curscope++
  1528  	for curscope < int32(len(scopes)) {
  1529  		scope := scopes[curscope]
  1530  		if scope.Parent != this {
  1531  			return curscope
  1532  		}
  1533  
  1534  		if len(scopes[curscope].Vars) == 0 {
  1535  			curscope = putscope(ctxt, s, scopes, curscope, fnabbrev, encbuf)
  1536  			continue
  1537  		}
  1538  
  1539  		// For DWARF 5, we always use the ranges form of the abbrev, since
  1540  		// it is more compact than using explicit hi/lo PC attrs.  See
  1541  		// issue #72821 for more on why this makes sense.
  1542  		if len(scope.Ranges) == 1 && !buildcfg.Experiment.Dwarf5 {
  1543  			Uleb128put(ctxt, s.Info, DW_ABRV_LEXICAL_BLOCK_SIMPLE)
  1544  			putattr(ctxt, s.Info, DW_ABRV_LEXICAL_BLOCK_SIMPLE, DW_FORM_addr, DW_CLS_ADDRESS, scope.Ranges[0].Start, s.StartPC)
  1545  			putattr(ctxt, s.Info, DW_ABRV_LEXICAL_BLOCK_SIMPLE, DW_FORM_addr, DW_CLS_ADDRESS, scope.Ranges[0].End, s.StartPC)
  1546  		} else {
  1547  			Uleb128put(ctxt, s.Info, DW_ABRV_LEXICAL_BLOCK_RANGES)
  1548  			putattr(ctxt, s.Info, DW_ABRV_LEXICAL_BLOCK_RANGES, DW_FORM_sec_offset, DW_CLS_PTR, ctxt.Size(s.Ranges), s.Ranges)
  1549  
  1550  			s.PutRanges(ctxt, scope.Ranges)
  1551  		}
  1552  
  1553  		curscope = putscope(ctxt, s, scopes, curscope, fnabbrev, encbuf)
  1554  
  1555  		Uleb128put(ctxt, s.Info, 0)
  1556  	}
  1557  	return curscope
  1558  }
  1559  
  1560  func concreteVar(fnabbrev int, v *Var) bool {
  1561  	concrete := true
  1562  	switch fnabbrev {
  1563  	case DW_ABRV_FUNCTION, DW_ABRV_WRAPPER:
  1564  		concrete = false
  1565  	case DW_ABRV_FUNCTION_CONCRETE, DW_ABRV_WRAPPER_CONCRETE:
  1566  		// If we're emitting a concrete subprogram DIE and the variable
  1567  		// in question is not part of the corresponding abstract function DIE,
  1568  		// then use the default (non-concrete) abbrev for this param.
  1569  		if !v.IsInAbstract {
  1570  			concrete = false
  1571  		}
  1572  	case DW_ABRV_INLINED_SUBROUTINE, DW_ABRV_INLINED_SUBROUTINE_RANGES:
  1573  	default:
  1574  		panic("should never happen")
  1575  	}
  1576  	return concrete
  1577  }
  1578  
  1579  // Emit DWARF attributes for a variable belonging to an 'abstract' subprogram.
  1580  func putAbstractVar(ctxt Context, info Sym, v *Var) {
  1581  	// The contents of this functions are used to generate putAbstractVarAbbrev automatically, see TestPutVarAbbrevGenerator.
  1582  	abbrev := putAbstractVarAbbrev(v)
  1583  	Uleb128put(ctxt, info, int64(abbrev))
  1584  	putattr(ctxt, info, abbrev, DW_FORM_string, DW_CLS_STRING, int64(len(v.Name)), v.Name) // DW_AT_name
  1585  
  1586  	// Isreturn attribute if this is a param
  1587  	if v.Tag == DW_TAG_formal_parameter {
  1588  		var isReturn int64
  1589  		if v.IsReturnValue {
  1590  			isReturn = 1
  1591  		}
  1592  		putattr(ctxt, info, abbrev, DW_FORM_flag, DW_CLS_FLAG, isReturn, nil) // DW_AT_variable_parameter
  1593  	}
  1594  
  1595  	// Line
  1596  	if v.Tag == DW_TAG_variable {
  1597  		// See issue 23374 for more on why decl line is skipped for abs params.
  1598  		putattr(ctxt, info, abbrev, DW_FORM_udata, DW_CLS_CONSTANT, int64(v.DeclLine), nil) // DW_AT_decl_line
  1599  	}
  1600  
  1601  	// Type
  1602  	putattr(ctxt, info, abbrev, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, v.Type) // DW_AT_type
  1603  
  1604  	// Var has no children => no terminator
  1605  }
  1606  
  1607  func putvar(ctxt Context, s *FnState, v *Var, absfn Sym, fnabbrev, inlIndex int, encbuf []byte) {
  1608  	// The contents of this functions are used to generate putvarAbbrev automatically, see TestPutVarAbbrevGenerator.
  1609  	concrete := concreteVar(fnabbrev, v)
  1610  	hasParametricType := !concrete && (v.DictIndex > 0 && s.dictIndexToOffset != nil && s.dictIndexToOffset[v.DictIndex-1] != 0)
  1611  	withLoclist := v.WithLoclist && v.PutLocationList != nil
  1612  
  1613  	abbrev := putvarAbbrev(v, concrete, withLoclist)
  1614  	Uleb128put(ctxt, s.Info, int64(abbrev))
  1615  
  1616  	// Abstract origin for concrete / inlined case
  1617  	if concrete {
  1618  		// Here we are making a reference to a child DIE of an abstract
  1619  		// function subprogram DIE. The child DIE has no LSym, so instead
  1620  		// after the call to 'putattr' below we make a call to register
  1621  		// the child DIE reference.
  1622  		putattr(ctxt, s.Info, abbrev, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, absfn) // DW_AT_abstract_origin
  1623  		ctxt.RecordDclReference(s.Info, absfn, int(v.ChildIndex), inlIndex)
  1624  	} else {
  1625  		// Var name, line for abstract and default cases
  1626  		n := v.Name
  1627  		putattr(ctxt, s.Info, abbrev, DW_FORM_string, DW_CLS_STRING, int64(len(n)), n) // DW_AT_name
  1628  		if v.Tag == DW_TAG_formal_parameter {
  1629  			var isReturn int64
  1630  			if v.IsReturnValue {
  1631  				isReturn = 1
  1632  			}
  1633  			putattr(ctxt, s.Info, abbrev, DW_FORM_flag, DW_CLS_FLAG, isReturn, nil) // DW_AT_variable_parameter
  1634  		}
  1635  		putattr(ctxt, s.Info, abbrev, DW_FORM_udata, DW_CLS_CONSTANT, int64(v.DeclLine), nil) // DW_AT_decl_line
  1636  		if hasParametricType {
  1637  			// If the type of this variable is parametric use the entry emitted by putparamtypes
  1638  			putattr(ctxt, s.Info, abbrev, DW_FORM_ref_addr, DW_CLS_REFERENCE, s.dictIndexToOffset[v.DictIndex-1], s.Info) // DW_AT_type
  1639  		} else {
  1640  			putattr(ctxt, s.Info, abbrev, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, v.Type) // DW_AT_type
  1641  		}
  1642  
  1643  		if v.ClosureOffset > 0 {
  1644  			putattr(ctxt, s.Info, abbrev, DW_FORM_udata, DW_CLS_CONSTANT, v.ClosureOffset, nil) // DW_AT_go_closure_offset
  1645  		}
  1646  	}
  1647  
  1648  	if withLoclist {
  1649  		putattr(ctxt, s.Info, abbrev, DW_FORM_sec_offset, DW_CLS_PTR, ctxt.Size(s.Loc), s.Loc) // DW_AT_location
  1650  		v.PutLocationList(s.Loc, s.StartPC)
  1651  	} else {
  1652  		loc := encbuf[:0]
  1653  		switch {
  1654  		case v.WithLoclist:
  1655  			break // no location
  1656  		case v.StackOffset == 0:
  1657  			loc = append(loc, DW_OP_call_frame_cfa)
  1658  		default:
  1659  			loc = append(loc, DW_OP_fbreg)
  1660  			loc = AppendSleb128(loc, int64(v.StackOffset))
  1661  		}
  1662  		putattr(ctxt, s.Info, abbrev, DW_FORM_block1, DW_CLS_BLOCK, int64(len(loc)), loc) // DW_AT_location
  1663  	}
  1664  
  1665  	// Var has no children => no terminator
  1666  }
  1667  
  1668  // byChildIndexCmp compares two *dwarf.Var by child index.
  1669  func byChildIndexCmp(a, b *Var) int { return cmp.Compare(a.ChildIndex, b.ChildIndex) }
  1670  
  1671  // IsDWARFEnabledOnAIXLd returns true if DWARF is possible on the
  1672  // current extld.
  1673  // AIX ld doesn't support DWARF with -bnoobjreorder with version
  1674  // prior to 7.2.2.
  1675  func IsDWARFEnabledOnAIXLd(extld []string) (bool, error) {
  1676  	name, args := extld[0], extld[1:]
  1677  	args = append(args, "-Wl,-V")
  1678  	out, err := exec.Command(name, args...).CombinedOutput()
  1679  	if err != nil {
  1680  		// The normal output should display ld version and
  1681  		// then fails because ".main" is not defined:
  1682  		// ld: 0711-317 ERROR: Undefined symbol: .main
  1683  		if !bytes.Contains(out, []byte("0711-317")) {
  1684  			return false, fmt.Errorf("%s -Wl,-V failed: %v\n%s", extld, err, out)
  1685  		}
  1686  	}
  1687  	// gcc -Wl,-V output should be:
  1688  	//   /usr/bin/ld: LD X.X.X(date)
  1689  	//   ...
  1690  	out = bytes.TrimPrefix(out, []byte("/usr/bin/ld: LD "))
  1691  	vers := string(bytes.Split(out, []byte("("))[0])
  1692  	subvers := strings.Split(vers, ".")
  1693  	if len(subvers) != 3 {
  1694  		return false, fmt.Errorf("cannot parse %s -Wl,-V (%s): %v\n", extld, out, err)
  1695  	}
  1696  	if v, err := strconv.Atoi(subvers[0]); err != nil || v < 7 {
  1697  		return false, nil
  1698  	} else if v > 7 {
  1699  		return true, nil
  1700  	}
  1701  	if v, err := strconv.Atoi(subvers[1]); err != nil || v < 2 {
  1702  		return false, nil
  1703  	} else if v > 2 {
  1704  		return true, nil
  1705  	}
  1706  	if v, err := strconv.Atoi(subvers[2]); err != nil || v < 2 {
  1707  		return false, nil
  1708  	}
  1709  	return true, nil
  1710  }
  1711  

View as plain text