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_PUTVAR_START
   360  )
   361  
   362  type dwAbbrev struct {
   363  	tag      uint8
   364  	children uint8
   365  	attr     []dwAttrForm
   366  }
   367  
   368  var abbrevsFinalized bool
   369  
   370  // expandPseudoForm takes an input DW_FORM_xxx value and translates it
   371  // into a version- and platform-appropriate concrete form. Existing
   372  // concrete/real DW_FORM values are left untouched. For the moment the
   373  // only platform-specific pseudo-form is DW_FORM_udata_pseudo, which
   374  // gets expanded to DW_FORM_data4 on Darwin and DW_FORM_udata
   375  // everywhere else. See issue #31459 for more context. Then we have a
   376  // pair of pseudo-forms for lo and hi PC attributes, which are
   377  // expanded differently depending on whether we're generating DWARF
   378  // version 4 or 5.
   379  func expandPseudoForm(form uint8) uint8 {
   380  	switch form {
   381  	case DW_FORM_udata_pseudo:
   382  		expandedForm := DW_FORM_udata
   383  		if buildcfg.GOOS == "darwin" || buildcfg.GOOS == "ios" {
   384  			expandedForm = DW_FORM_data4
   385  		}
   386  		return uint8(expandedForm)
   387  	case DW_FORM_lo_pc_pseudo:
   388  		if buildcfg.Experiment.Dwarf5 {
   389  			return DW_FORM_addrx
   390  		}
   391  		return DW_FORM_addr
   392  	case DW_FORM_hi_pc_pseudo:
   393  		if buildcfg.Experiment.Dwarf5 {
   394  			return DW_FORM_udata
   395  		}
   396  		return DW_FORM_addr
   397  	default:
   398  		return form
   399  	}
   400  }
   401  
   402  // Abbrevs returns the finalized abbrev array for the platform,
   403  // expanding any DW_FORM pseudo-ops to real values.
   404  func Abbrevs() []dwAbbrev {
   405  	if abbrevsFinalized {
   406  		return abbrevs
   407  	}
   408  	abbrevs = append(abbrevs, putvarAbbrevs...)
   409  	for i := 1; i < len(abbrevs); i++ {
   410  		for j := 0; j < len(abbrevs[i].attr); j++ {
   411  			abbrevs[i].attr[j].form = expandPseudoForm(abbrevs[i].attr[j].form)
   412  		}
   413  	}
   414  	if buildcfg.Experiment.Dwarf5 {
   415  		// Tack on a new DW_AT_addr_base attribute to the compunit DIE,
   416  		// which will point to the offset in the .debug_addr section
   417  		// containing entries for this comp unit (this attr gets
   418  		// fixed up in the linker).
   419  		for i := 1; i < len(abbrevs); i++ {
   420  			haveLo := false
   421  			for j := 0; j < len(abbrevs[i].attr); j++ {
   422  				if abbrevs[i].attr[j].attr == DW_AT_low_pc {
   423  					haveLo = true
   424  				}
   425  			}
   426  			if abbrevs[i].tag == DW_TAG_compile_unit && haveLo {
   427  				abbrevs[i].attr = append(abbrevs[i].attr,
   428  					dwAttrForm{DW_AT_addr_base, DW_FORM_sec_offset})
   429  			}
   430  		}
   431  	}
   432  
   433  	abbrevsFinalized = true
   434  	return abbrevs
   435  }
   436  
   437  // abbrevs is a raw table of abbrev entries; it needs to be post-processed
   438  // by the Abbrevs() function above prior to being consumed, to expand
   439  // the 'pseudo-form' entries below to real DWARF form values.
   440  
   441  var abbrevs = []dwAbbrev{
   442  	/* The mandatory DW_ABRV_NULL entry. */
   443  	{0, 0, []dwAttrForm{}},
   444  
   445  	/* COMPUNIT */
   446  	{
   447  		DW_TAG_compile_unit,
   448  		DW_CHILDREN_yes,
   449  		[]dwAttrForm{
   450  			{DW_AT_name, DW_FORM_string},
   451  			{DW_AT_language, DW_FORM_data1},
   452  			{DW_AT_stmt_list, DW_FORM_sec_offset},
   453  			{DW_AT_low_pc, DW_FORM_addr},
   454  			{DW_AT_ranges, DW_FORM_sec_offset},
   455  			{DW_AT_comp_dir, DW_FORM_string},
   456  			{DW_AT_producer, DW_FORM_string},
   457  			{DW_AT_go_package_name, DW_FORM_string},
   458  			// NB: DWARF5 adds DW_AT_addr_base here.
   459  		},
   460  	},
   461  
   462  	/* COMPUNIT_TEXTLESS */
   463  	{
   464  		DW_TAG_compile_unit,
   465  		DW_CHILDREN_yes,
   466  		[]dwAttrForm{
   467  			{DW_AT_name, DW_FORM_string},
   468  			{DW_AT_language, DW_FORM_data1},
   469  			{DW_AT_comp_dir, DW_FORM_string},
   470  			{DW_AT_producer, DW_FORM_string},
   471  			{DW_AT_go_package_name, DW_FORM_string},
   472  		},
   473  	},
   474  
   475  	/* FUNCTION */
   476  	{
   477  		DW_TAG_subprogram,
   478  		DW_CHILDREN_yes,
   479  		[]dwAttrForm{
   480  			{DW_AT_name, DW_FORM_string},
   481  			{DW_AT_low_pc, DW_FORM_lo_pc_pseudo},
   482  			{DW_AT_high_pc, DW_FORM_hi_pc_pseudo},
   483  			{DW_AT_frame_base, DW_FORM_block1},
   484  			{DW_AT_decl_file, DW_FORM_data4},
   485  			{DW_AT_decl_line, DW_FORM_udata},
   486  			{DW_AT_external, DW_FORM_flag},
   487  		},
   488  	},
   489  
   490  	/* WRAPPER */
   491  	{
   492  		DW_TAG_subprogram,
   493  		DW_CHILDREN_yes,
   494  		[]dwAttrForm{
   495  			{DW_AT_name, DW_FORM_string},
   496  			{DW_AT_low_pc, DW_FORM_lo_pc_pseudo},
   497  			{DW_AT_high_pc, DW_FORM_hi_pc_pseudo},
   498  			{DW_AT_frame_base, DW_FORM_block1},
   499  			{DW_AT_trampoline, DW_FORM_flag},
   500  		},
   501  	},
   502  
   503  	/* FUNCTION_ABSTRACT */
   504  	{
   505  		DW_TAG_subprogram,
   506  		DW_CHILDREN_yes,
   507  		[]dwAttrForm{
   508  			{DW_AT_name, DW_FORM_string},
   509  			{DW_AT_inline, DW_FORM_data1},
   510  			{DW_AT_decl_line, DW_FORM_udata},
   511  			{DW_AT_external, DW_FORM_flag},
   512  		},
   513  	},
   514  
   515  	/* FUNCTION_CONCRETE */
   516  	{
   517  		DW_TAG_subprogram,
   518  		DW_CHILDREN_yes,
   519  		[]dwAttrForm{
   520  			{DW_AT_abstract_origin, DW_FORM_ref_addr},
   521  			{DW_AT_low_pc, DW_FORM_lo_pc_pseudo},
   522  			{DW_AT_high_pc, DW_FORM_hi_pc_pseudo},
   523  			{DW_AT_frame_base, DW_FORM_block1},
   524  		},
   525  	},
   526  
   527  	/* WRAPPER_CONCRETE */
   528  	{
   529  		DW_TAG_subprogram,
   530  		DW_CHILDREN_yes,
   531  		[]dwAttrForm{
   532  			{DW_AT_abstract_origin, DW_FORM_ref_addr},
   533  			{DW_AT_low_pc, DW_FORM_lo_pc_pseudo},
   534  			{DW_AT_high_pc, DW_FORM_hi_pc_pseudo},
   535  			{DW_AT_frame_base, DW_FORM_block1},
   536  			{DW_AT_trampoline, DW_FORM_flag},
   537  		},
   538  	},
   539  
   540  	/* INLINED_SUBROUTINE */
   541  	{
   542  		DW_TAG_inlined_subroutine,
   543  		DW_CHILDREN_yes,
   544  		[]dwAttrForm{
   545  			{DW_AT_abstract_origin, DW_FORM_ref_addr},
   546  			{DW_AT_low_pc, DW_FORM_lo_pc_pseudo},
   547  			{DW_AT_high_pc, DW_FORM_hi_pc_pseudo},
   548  			{DW_AT_call_file, DW_FORM_data4},
   549  			{DW_AT_call_line, DW_FORM_udata_pseudo}, // pseudo-form
   550  		},
   551  	},
   552  
   553  	/* INLINED_SUBROUTINE_RANGES */
   554  	{
   555  		DW_TAG_inlined_subroutine,
   556  		DW_CHILDREN_yes,
   557  		[]dwAttrForm{
   558  			{DW_AT_abstract_origin, DW_FORM_ref_addr},
   559  			{DW_AT_ranges, DW_FORM_sec_offset},
   560  			{DW_AT_call_file, DW_FORM_data4},
   561  			{DW_AT_call_line, DW_FORM_udata_pseudo}, // pseudo-form
   562  		},
   563  	},
   564  
   565  	/* VARIABLE */
   566  	{
   567  		DW_TAG_variable,
   568  		DW_CHILDREN_no,
   569  		[]dwAttrForm{
   570  			{DW_AT_name, DW_FORM_string},
   571  			{DW_AT_location, DW_FORM_block1},
   572  			{DW_AT_type, DW_FORM_ref_addr},
   573  			{DW_AT_external, DW_FORM_flag},
   574  		},
   575  	},
   576  
   577  	/* INT CONSTANT */
   578  	{
   579  		DW_TAG_constant,
   580  		DW_CHILDREN_no,
   581  		[]dwAttrForm{
   582  			{DW_AT_name, DW_FORM_string},
   583  			{DW_AT_type, DW_FORM_ref_addr},
   584  			{DW_AT_const_value, DW_FORM_sdata},
   585  		},
   586  	},
   587  
   588  	/* LEXICAL_BLOCK_RANGES */
   589  	{
   590  		DW_TAG_lexical_block,
   591  		DW_CHILDREN_yes,
   592  		[]dwAttrForm{
   593  			{DW_AT_ranges, DW_FORM_sec_offset},
   594  		},
   595  	},
   596  
   597  	/* LEXICAL_BLOCK_SIMPLE */
   598  	{
   599  		DW_TAG_lexical_block,
   600  		DW_CHILDREN_yes,
   601  		[]dwAttrForm{
   602  			// Note: unused if we are generating DWARF 5, we
   603  			// use the ranges form even if there is a singleton range.
   604  			{DW_AT_low_pc, DW_FORM_addr},
   605  			{DW_AT_high_pc, DW_FORM_addr},
   606  		},
   607  	},
   608  
   609  	/* STRUCTFIELD */
   610  	{
   611  		DW_TAG_member,
   612  		DW_CHILDREN_no,
   613  		// This abbrev is special-cased by the linker (unlike other DIEs
   614  		// we don't want a loader.Sym created for this DIE).
   615  		[]dwAttrForm{
   616  			{DW_AT_name, DW_FORM_string},
   617  			{DW_AT_data_member_location, DW_FORM_udata},
   618  			{DW_AT_type, DW_FORM_ref_addr},
   619  			{DW_AT_go_embedded_field, DW_FORM_flag},
   620  		},
   621  	},
   622  
   623  	/* FUNCTYPEPARAM */
   624  	{
   625  		DW_TAG_formal_parameter,
   626  		DW_CHILDREN_no,
   627  
   628  		// No name!
   629  		// This abbrev is special-cased by the linker (unlike other DIEs
   630  		// we don't want a loader.Sym created for this DIE).
   631  		[]dwAttrForm{
   632  			{DW_AT_type, DW_FORM_ref_addr},
   633  		},
   634  	},
   635  
   636  	/* FUNCTYPEOUTPARAM */
   637  	{
   638  		DW_TAG_formal_parameter,
   639  		DW_CHILDREN_no,
   640  
   641  		// No name!
   642  		// This abbrev is special-cased by the linker (unlike other DIEs
   643  		// we don't want a loader.Sym created for this DIE).
   644  		[]dwAttrForm{
   645  			{DW_AT_variable_parameter, DW_FORM_flag},
   646  			{DW_AT_type, DW_FORM_ref_addr},
   647  		},
   648  	},
   649  
   650  	/* DOTDOTDOT */
   651  	{
   652  		DW_TAG_unspecified_parameters,
   653  		DW_CHILDREN_no,
   654  		// No name.
   655  		// This abbrev is special-cased by the linker (unlike other DIEs
   656  		// we don't want a loader.Sym created for this DIE).
   657  		[]dwAttrForm{},
   658  	},
   659  
   660  	/* ARRAYRANGE */
   661  	{
   662  		DW_TAG_subrange_type,
   663  		DW_CHILDREN_no,
   664  
   665  		// No name!
   666  		// This abbrev is special-cased by the linker (unlike other DIEs
   667  		// we don't want a loader.Sym created for this DIE).
   668  		[]dwAttrForm{
   669  			{DW_AT_type, DW_FORM_ref_addr},
   670  			{DW_AT_count, DW_FORM_udata},
   671  		},
   672  	},
   673  
   674  	// Below here are the types considered public by ispubtype
   675  	/* NULLTYPE */
   676  	{
   677  		DW_TAG_unspecified_type,
   678  		DW_CHILDREN_no,
   679  		[]dwAttrForm{
   680  			{DW_AT_name, DW_FORM_string},
   681  		},
   682  	},
   683  
   684  	/* BASETYPE */
   685  	{
   686  		DW_TAG_base_type,
   687  		DW_CHILDREN_no,
   688  		[]dwAttrForm{
   689  			{DW_AT_name, DW_FORM_string},
   690  			{DW_AT_encoding, DW_FORM_data1},
   691  			{DW_AT_byte_size, DW_FORM_data1},
   692  			{DW_AT_go_kind, DW_FORM_data1},
   693  			{DW_AT_go_runtime_type, DW_FORM_addr},
   694  		},
   695  	},
   696  
   697  	/* ARRAYTYPE */
   698  	// child is subrange with upper bound
   699  	{
   700  		DW_TAG_array_type,
   701  		DW_CHILDREN_yes,
   702  		[]dwAttrForm{
   703  			{DW_AT_name, DW_FORM_string},
   704  			{DW_AT_type, DW_FORM_ref_addr},
   705  			{DW_AT_byte_size, DW_FORM_udata},
   706  			{DW_AT_go_kind, DW_FORM_data1},
   707  			{DW_AT_go_runtime_type, DW_FORM_addr},
   708  		},
   709  	},
   710  
   711  	/* CHANTYPE */
   712  	{
   713  		DW_TAG_typedef,
   714  		DW_CHILDREN_no,
   715  		[]dwAttrForm{
   716  			{DW_AT_name, DW_FORM_string},
   717  			{DW_AT_type, DW_FORM_ref_addr},
   718  			{DW_AT_go_kind, DW_FORM_data1},
   719  			{DW_AT_go_runtime_type, DW_FORM_addr},
   720  			{DW_AT_go_elem, DW_FORM_ref_addr},
   721  		},
   722  	},
   723  
   724  	/* FUNCTYPE */
   725  	{
   726  		DW_TAG_subroutine_type,
   727  		DW_CHILDREN_yes,
   728  		[]dwAttrForm{
   729  			{DW_AT_name, DW_FORM_string},
   730  			{DW_AT_byte_size, DW_FORM_udata},
   731  			{DW_AT_go_kind, DW_FORM_data1},
   732  			{DW_AT_go_runtime_type, DW_FORM_addr},
   733  		},
   734  	},
   735  
   736  	/* IFACETYPE */
   737  	{
   738  		DW_TAG_typedef,
   739  		DW_CHILDREN_yes,
   740  		[]dwAttrForm{
   741  			{DW_AT_name, DW_FORM_string},
   742  			{DW_AT_type, DW_FORM_ref_addr},
   743  			{DW_AT_go_kind, DW_FORM_data1},
   744  			{DW_AT_go_runtime_type, DW_FORM_addr},
   745  		},
   746  	},
   747  
   748  	/* MAPTYPE */
   749  	{
   750  		DW_TAG_typedef,
   751  		DW_CHILDREN_no,
   752  		[]dwAttrForm{
   753  			{DW_AT_name, DW_FORM_string},
   754  			{DW_AT_type, DW_FORM_ref_addr},
   755  			{DW_AT_go_kind, DW_FORM_data1},
   756  			{DW_AT_go_runtime_type, DW_FORM_addr},
   757  			{DW_AT_go_key, DW_FORM_ref_addr},
   758  			{DW_AT_go_elem, DW_FORM_ref_addr},
   759  		},
   760  	},
   761  
   762  	/* PTRTYPE */
   763  	{
   764  		DW_TAG_pointer_type,
   765  		DW_CHILDREN_no,
   766  		[]dwAttrForm{
   767  			{DW_AT_name, DW_FORM_string},
   768  			{DW_AT_type, DW_FORM_ref_addr},
   769  			{DW_AT_go_kind, DW_FORM_data1},
   770  			{DW_AT_go_runtime_type, DW_FORM_addr},
   771  		},
   772  	},
   773  
   774  	/* BARE_PTRTYPE */
   775  	{
   776  		DW_TAG_pointer_type,
   777  		DW_CHILDREN_no,
   778  		[]dwAttrForm{
   779  			{DW_AT_name, DW_FORM_string},
   780  			{DW_AT_go_runtime_type, DW_FORM_addr},
   781  		},
   782  	},
   783  
   784  	/* SLICETYPE */
   785  	{
   786  		DW_TAG_structure_type,
   787  		DW_CHILDREN_yes,
   788  		[]dwAttrForm{
   789  			{DW_AT_name, DW_FORM_string},
   790  			{DW_AT_byte_size, DW_FORM_udata},
   791  			{DW_AT_go_kind, DW_FORM_data1},
   792  			{DW_AT_go_runtime_type, DW_FORM_addr},
   793  			{DW_AT_go_elem, DW_FORM_ref_addr},
   794  		},
   795  	},
   796  
   797  	/* STRINGTYPE */
   798  	{
   799  		DW_TAG_structure_type,
   800  		DW_CHILDREN_yes,
   801  		[]dwAttrForm{
   802  			{DW_AT_name, DW_FORM_string},
   803  			{DW_AT_byte_size, DW_FORM_udata},
   804  			{DW_AT_go_kind, DW_FORM_data1},
   805  			{DW_AT_go_runtime_type, DW_FORM_addr},
   806  		},
   807  	},
   808  
   809  	/* STRUCTTYPE */
   810  	{
   811  		DW_TAG_structure_type,
   812  		DW_CHILDREN_yes,
   813  		[]dwAttrForm{
   814  			{DW_AT_name, DW_FORM_string},
   815  			{DW_AT_byte_size, DW_FORM_udata},
   816  			{DW_AT_go_kind, DW_FORM_data1},
   817  			{DW_AT_go_runtime_type, DW_FORM_addr},
   818  		},
   819  	},
   820  
   821  	/* TYPEDECL */
   822  	{
   823  		DW_TAG_typedef,
   824  		DW_CHILDREN_no,
   825  		[]dwAttrForm{
   826  			{DW_AT_name, DW_FORM_string},
   827  			{DW_AT_type, DW_FORM_ref_addr},
   828  		},
   829  	},
   830  
   831  	/* DICT_INDEX */
   832  	{
   833  		DW_TAG_typedef,
   834  		DW_CHILDREN_no,
   835  		[]dwAttrForm{
   836  			{DW_AT_name, DW_FORM_string},
   837  			{DW_AT_type, DW_FORM_ref_addr},
   838  			{DW_AT_go_dict_index, DW_FORM_udata},
   839  		},
   840  	},
   841  }
   842  
   843  // GetAbbrev returns the contents of the .debug_abbrev section.
   844  func GetAbbrev() []byte {
   845  	abbrevs := Abbrevs()
   846  	var buf []byte
   847  	for i := 1; i < len(abbrevs); i++ {
   848  		// See section 7.5.3
   849  		buf = AppendUleb128(buf, uint64(i))
   850  		buf = AppendUleb128(buf, uint64(abbrevs[i].tag))
   851  		buf = append(buf, abbrevs[i].children)
   852  		for _, f := range abbrevs[i].attr {
   853  			buf = AppendUleb128(buf, uint64(f.attr))
   854  			buf = AppendUleb128(buf, uint64(f.form))
   855  		}
   856  		buf = append(buf, 0, 0)
   857  	}
   858  	return append(buf, 0)
   859  }
   860  
   861  /*
   862   * Debugging Information Entries and their attributes.
   863   */
   864  
   865  // DWAttr represents an attribute of a DWDie.
   866  //
   867  // For DW_CLS_string and _block, value should contain the length, and
   868  // data the data, for _reference, value is 0 and data is a DWDie* to
   869  // the referenced instance, for all others, value is the whole thing
   870  // and data is null.
   871  type DWAttr struct {
   872  	Link  *DWAttr
   873  	Atr   uint16 // DW_AT_
   874  	Cls   uint8  // DW_CLS_
   875  	Value int64
   876  	Data  any
   877  }
   878  
   879  // DWDie represents a DWARF debug info entry.
   880  type DWDie struct {
   881  	Abbrev int
   882  	Link   *DWDie
   883  	Child  *DWDie
   884  	Attr   *DWAttr
   885  	Sym    Sym
   886  }
   887  
   888  func putattr(ctxt Context, s Sym, abbrev int, form int, cls int, value int64, data any) error {
   889  	switch form {
   890  	case DW_FORM_addr: // address
   891  		// Allow nil addresses for DW_AT_go_runtime_type.
   892  		if data == nil && value == 0 {
   893  			ctxt.AddInt(s, ctxt.PtrSize(), 0)
   894  			break
   895  		}
   896  		if cls == DW_CLS_GO_TYPEREF {
   897  			ctxt.AddSectionOffset(s, ctxt.PtrSize(), data, value)
   898  			break
   899  		}
   900  		ctxt.AddAddress(s, data, value)
   901  
   902  	case DW_FORM_block1: // block
   903  		if cls == DW_CLS_ADDRESS {
   904  			ctxt.AddInt(s, 1, int64(1+ctxt.PtrSize()))
   905  			ctxt.AddInt(s, 1, DW_OP_addr)
   906  			ctxt.AddAddress(s, data, 0)
   907  			break
   908  		}
   909  
   910  		value &= 0xff
   911  		ctxt.AddInt(s, 1, value)
   912  		p := data.([]byte)[:value]
   913  		ctxt.AddBytes(s, p)
   914  
   915  	case DW_FORM_block2: // block
   916  		value &= 0xffff
   917  
   918  		ctxt.AddInt(s, 2, value)
   919  		p := data.([]byte)[:value]
   920  		ctxt.AddBytes(s, p)
   921  
   922  	case DW_FORM_block4: // block
   923  		value &= 0xffffffff
   924  
   925  		ctxt.AddInt(s, 4, value)
   926  		p := data.([]byte)[:value]
   927  		ctxt.AddBytes(s, p)
   928  
   929  	case DW_FORM_block: // block
   930  		Uleb128put(ctxt, s, value)
   931  
   932  		p := data.([]byte)[:value]
   933  		ctxt.AddBytes(s, p)
   934  
   935  	case DW_FORM_data1: // constant
   936  		ctxt.AddInt(s, 1, value)
   937  
   938  	case DW_FORM_data2: // constant
   939  		ctxt.AddInt(s, 2, value)
   940  
   941  	case DW_FORM_data4: // constant, {line,loclist,mac,rangelist}ptr
   942  		if cls == DW_CLS_PTR { // DW_AT_stmt_list and DW_AT_ranges
   943  			ctxt.AddDWARFAddrSectionOffset(s, data, value)
   944  			break
   945  		}
   946  		ctxt.AddInt(s, 4, value)
   947  
   948  	case DW_FORM_data8: // constant, {line,loclist,mac,rangelist}ptr
   949  		ctxt.AddInt(s, 8, value)
   950  
   951  	case DW_FORM_sdata: // constant
   952  		Sleb128put(ctxt, s, value)
   953  
   954  	case DW_FORM_udata: // constant
   955  		Uleb128put(ctxt, s, value)
   956  
   957  	case DW_FORM_string: // string
   958  		str := data.(string)
   959  		ctxt.AddString(s, str)
   960  		// TODO(ribrdb): verify padded strings are never used and remove this
   961  		for i := int64(len(str)); i < value; i++ {
   962  			ctxt.AddInt(s, 1, 0)
   963  		}
   964  
   965  	case DW_FORM_flag: // flag
   966  		if value != 0 {
   967  			ctxt.AddInt(s, 1, 1)
   968  		} else {
   969  			ctxt.AddInt(s, 1, 0)
   970  		}
   971  
   972  	// As of DWARF 3 the ref_addr is always 32 bits, unless emitting a large
   973  	// (> 4 GB of debug info aka "64-bit") unit, which we don't implement.
   974  	case DW_FORM_ref_addr: // reference to a DIE in the .info section
   975  		fallthrough
   976  	case DW_FORM_sec_offset: // offset into a DWARF section other than .info
   977  		if data == nil {
   978  			return fmt.Errorf("dwarf: null reference in %d", abbrev)
   979  		}
   980  		ctxt.AddDWARFAddrSectionOffset(s, data, value)
   981  
   982  	case DW_FORM_addrx: // index into .debug_addr section
   983  		ctxt.AddIndirectTextRef(s, data)
   984  
   985  	case DW_FORM_ref1, // reference within the compilation unit
   986  		DW_FORM_ref2,      // reference
   987  		DW_FORM_ref4,      // reference
   988  		DW_FORM_ref8,      // reference
   989  		DW_FORM_ref_udata, // reference
   990  
   991  		DW_FORM_strp,     // string
   992  		DW_FORM_indirect: // (see Section 7.5.3)
   993  		fallthrough
   994  	default:
   995  		return fmt.Errorf("dwarf: unsupported attribute form %d / class %d", form, cls)
   996  	}
   997  	return nil
   998  }
   999  
  1000  // PutAttrs writes the attributes for a DIE to symbol 's'.
  1001  //
  1002  // Note that we can (and do) add arbitrary attributes to a DIE, but
  1003  // only the ones actually listed in the Abbrev will be written out.
  1004  func PutAttrs(ctxt Context, s Sym, abbrev int, attr *DWAttr) {
  1005  	abbrevs := Abbrevs()
  1006  Outer:
  1007  	for _, f := range abbrevs[abbrev].attr {
  1008  		for ap := attr; ap != nil; ap = ap.Link {
  1009  			if ap.Atr == f.attr {
  1010  				putattr(ctxt, s, abbrev, int(f.form), int(ap.Cls), ap.Value, ap.Data)
  1011  				continue Outer
  1012  			}
  1013  		}
  1014  
  1015  		putattr(ctxt, s, abbrev, int(f.form), 0, 0, nil)
  1016  	}
  1017  }
  1018  
  1019  // HasChildren reports whether 'die' uses an abbrev that supports children.
  1020  func HasChildren(die *DWDie) bool {
  1021  	abbrevs := Abbrevs()
  1022  	return abbrevs[die.Abbrev].children != 0
  1023  }
  1024  
  1025  // PutIntConst writes a DIE for an integer constant
  1026  func PutIntConst(ctxt Context, info, typ Sym, name string, val int64) {
  1027  	Uleb128put(ctxt, info, DW_ABRV_INT_CONSTANT)
  1028  	putattr(ctxt, info, DW_ABRV_INT_CONSTANT, DW_FORM_string, DW_CLS_STRING, int64(len(name)), name)
  1029  	putattr(ctxt, info, DW_ABRV_INT_CONSTANT, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, typ)
  1030  	putattr(ctxt, info, DW_ABRV_INT_CONSTANT, DW_FORM_sdata, DW_CLS_CONSTANT, val, nil)
  1031  }
  1032  
  1033  // PutGlobal writes a DIE for a global variable.
  1034  func PutGlobal(ctxt Context, info, typ, gvar Sym, name string) {
  1035  	Uleb128put(ctxt, info, DW_ABRV_VARIABLE)
  1036  	putattr(ctxt, info, DW_ABRV_VARIABLE, DW_FORM_string, DW_CLS_STRING, int64(len(name)), name)
  1037  	putattr(ctxt, info, DW_ABRV_VARIABLE, DW_FORM_block1, DW_CLS_ADDRESS, 0, gvar)
  1038  	putattr(ctxt, info, DW_ABRV_VARIABLE, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, typ)
  1039  	putattr(ctxt, info, DW_ABRV_VARIABLE, DW_FORM_flag, DW_CLS_FLAG, 1, nil)
  1040  }
  1041  
  1042  // PutBasedRanges writes a range table to sym. All addresses in ranges are
  1043  // relative to some base address, which must be arranged by the caller
  1044  // (e.g., with a DW_AT_low_pc attribute, or in a BASE-prefixed range).
  1045  func PutBasedRanges(ctxt Context, sym Sym, ranges []Range) {
  1046  	ps := ctxt.PtrSize()
  1047  	// Write ranges.
  1048  	for _, r := range ranges {
  1049  		ctxt.AddInt(sym, ps, r.Start)
  1050  		ctxt.AddInt(sym, ps, r.End)
  1051  	}
  1052  	// Write trailer.
  1053  	ctxt.AddInt(sym, ps, 0)
  1054  	ctxt.AddInt(sym, ps, 0)
  1055  }
  1056  
  1057  // PutRngListRanges writes a DWARF5-style set of rangelist entries to sym,
  1058  // using base as a starting/base address.
  1059  func PutRngListRanges(ctxt Context, sym Sym, base Sym, ranges []Range) {
  1060  	addULEB128 := func(v int64) {
  1061  		b := sevenBitU(v)
  1062  		if b == nil {
  1063  			var encbuf [20]byte
  1064  			b = AppendUleb128(encbuf[:0], uint64(v))
  1065  		}
  1066  		ctxt.AddBytes(sym, b)
  1067  	}
  1068  	// First entry is base address.
  1069  	ctxt.AddInt(sym, 1, DW_RLE_base_addressx)
  1070  	ctxt.AddIndirectTextRef(sym, base)
  1071  	// Remaining entries are .debug_rnglist offset pairs
  1072  	for _, r := range ranges {
  1073  		ctxt.AddInt(sym, 1, DW_RLE_offset_pair)
  1074  		addULEB128(r.Start)
  1075  		addULEB128(r.End)
  1076  	}
  1077  	// Terminator to mark end of list
  1078  	ctxt.AddInt(sym, 1, DW_RLE_end_of_list)
  1079  }
  1080  
  1081  // PutRanges writes a range table to s.Ranges.
  1082  // All addresses in ranges are relative to s.base.
  1083  func (s *FnState) PutRanges(ctxt Context, ranges []Range) {
  1084  	ps := ctxt.PtrSize()
  1085  	sym, base := s.Ranges, s.StartPC
  1086  
  1087  	if buildcfg.Experiment.Dwarf5 {
  1088  		PutRngListRanges(ctxt, sym, base, ranges)
  1089  		return
  1090  	}
  1091  
  1092  	if s.UseBASEntries {
  1093  		// Using a Base Address Selection Entry reduces the number of relocations, but
  1094  		// this is not done on macOS because it is not supported by dsymutil/dwarfdump/lldb
  1095  		ctxt.AddInt(sym, ps, -1)
  1096  		ctxt.AddAddress(sym, base, 0)
  1097  		PutBasedRanges(ctxt, sym, ranges)
  1098  		return
  1099  	}
  1100  
  1101  	// Write ranges full of relocations
  1102  	for _, r := range ranges {
  1103  		ctxt.AddCURelativeAddress(sym, base, r.Start)
  1104  		ctxt.AddCURelativeAddress(sym, base, r.End)
  1105  	}
  1106  	// Write trailer.
  1107  	ctxt.AddInt(sym, ps, 0)
  1108  	ctxt.AddInt(sym, ps, 0)
  1109  }
  1110  
  1111  // Return TRUE if the inlined call in the specified slot is empty,
  1112  // meaning it has a zero-length range (no instructions), and all
  1113  // of its children are empty.
  1114  func isEmptyInlinedCall(slot int, calls *InlCalls) bool {
  1115  	ic := &calls.Calls[slot]
  1116  	if ic.InlIndex == -2 {
  1117  		return true
  1118  	}
  1119  	live := false
  1120  	for _, k := range ic.Children {
  1121  		if !isEmptyInlinedCall(k, calls) {
  1122  			live = true
  1123  		}
  1124  	}
  1125  	if len(ic.Ranges) > 0 {
  1126  		live = true
  1127  	}
  1128  	if !live {
  1129  		ic.InlIndex = -2
  1130  	}
  1131  	return !live
  1132  }
  1133  
  1134  // Slot -1:    return top-level inlines.
  1135  // Slot >= 0:  return children of that slot.
  1136  func inlChildren(slot int, calls *InlCalls) []int {
  1137  	var kids []int
  1138  	if slot != -1 {
  1139  		for _, k := range calls.Calls[slot].Children {
  1140  			if !isEmptyInlinedCall(k, calls) {
  1141  				kids = append(kids, k)
  1142  			}
  1143  		}
  1144  	} else {
  1145  		for k := 0; k < len(calls.Calls); k += 1 {
  1146  			if calls.Calls[k].Root && !isEmptyInlinedCall(k, calls) {
  1147  				kids = append(kids, k)
  1148  			}
  1149  		}
  1150  	}
  1151  	return kids
  1152  }
  1153  
  1154  func inlinedVarTable(inlcalls *InlCalls) map[*Var]bool {
  1155  	vars := make(map[*Var]bool)
  1156  	for _, ic := range inlcalls.Calls {
  1157  		for _, v := range ic.InlVars {
  1158  			vars[v] = true
  1159  		}
  1160  	}
  1161  	return vars
  1162  }
  1163  
  1164  // The s.Scopes slice contains variables were originally part of the
  1165  // function being emitted, as well as variables that were imported
  1166  // from various callee functions during the inlining process. This
  1167  // function prunes out any variables from the latter category (since
  1168  // they will be emitted as part of DWARF inlined_subroutine DIEs) and
  1169  // then generates scopes for vars in the former category.
  1170  func putPrunedScopes(ctxt Context, s *FnState, fnabbrev int) error {
  1171  	if len(s.Scopes) == 0 {
  1172  		return nil
  1173  	}
  1174  	scopes := make([]Scope, len(s.Scopes), len(s.Scopes))
  1175  	pvars := inlinedVarTable(&s.InlCalls)
  1176  	for k, s := range s.Scopes {
  1177  		var pruned Scope = Scope{Parent: s.Parent, Ranges: s.Ranges}
  1178  		for i := 0; i < len(s.Vars); i++ {
  1179  			_, found := pvars[s.Vars[i]]
  1180  			if !found {
  1181  				pruned.Vars = append(pruned.Vars, s.Vars[i])
  1182  			}
  1183  		}
  1184  		slices.SortFunc(pruned.Vars, byChildIndexCmp)
  1185  		scopes[k] = pruned
  1186  	}
  1187  
  1188  	s.dictIndexToOffset = putparamtypes(ctxt, s, scopes, fnabbrev)
  1189  
  1190  	var encbuf [20]byte
  1191  	if putscope(ctxt, s, scopes, 0, fnabbrev, encbuf[:0]) < int32(len(scopes)) {
  1192  		return errors.New("multiple toplevel scopes")
  1193  	}
  1194  	return nil
  1195  }
  1196  
  1197  // Emit DWARF attributes and child DIEs for an 'abstract' subprogram.
  1198  // The abstract subprogram DIE for a function contains its
  1199  // location-independent attributes (name, type, etc). Other instances
  1200  // of the function (any inlined copy of it, or the single out-of-line
  1201  // 'concrete' instance) will contain a pointer back to this abstract
  1202  // DIE (as a space-saving measure, so that name/type etc doesn't have
  1203  // to be repeated for each inlined copy).
  1204  func PutAbstractFunc(ctxt Context, s *FnState) error {
  1205  	if logDwarf {
  1206  		ctxt.Logf("PutAbstractFunc(%v)\n", s.Absfn)
  1207  	}
  1208  
  1209  	abbrev := DW_ABRV_FUNCTION_ABSTRACT
  1210  	Uleb128put(ctxt, s.Absfn, int64(abbrev))
  1211  
  1212  	fullname := s.Name
  1213  	if strings.HasPrefix(s.Name, `"".`) {
  1214  		return fmt.Errorf("unqualified symbol name: %v", s.Name)
  1215  	}
  1216  	putattr(ctxt, s.Absfn, abbrev, DW_FORM_string, DW_CLS_STRING, int64(len(fullname)), fullname)
  1217  
  1218  	// DW_AT_inlined value
  1219  	putattr(ctxt, s.Absfn, abbrev, DW_FORM_data1, DW_CLS_CONSTANT, int64(DW_INL_inlined), nil)
  1220  
  1221  	// TODO(mdempsky): Shouldn't we write out StartPos.FileIndex() too?
  1222  	putattr(ctxt, s.Absfn, abbrev, DW_FORM_udata, DW_CLS_CONSTANT, int64(s.StartPos.RelLine()), nil)
  1223  
  1224  	var ev int64
  1225  	if s.External {
  1226  		ev = 1
  1227  	}
  1228  	putattr(ctxt, s.Absfn, abbrev, DW_FORM_flag, DW_CLS_FLAG, ev, 0)
  1229  
  1230  	// Child variables (may be empty)
  1231  	var flattened []*Var
  1232  
  1233  	// This slice will hold the offset in bytes for each child var DIE
  1234  	// with respect to the start of the parent subprogram DIE.
  1235  	var offsets []int32
  1236  
  1237  	// Scopes/vars
  1238  	if len(s.Scopes) > 0 {
  1239  		// For abstract subprogram DIEs we want to flatten out scope info:
  1240  		// lexical scope DIEs contain range and/or hi/lo PC attributes,
  1241  		// which we explicitly don't want for the abstract subprogram DIE.
  1242  		pvars := inlinedVarTable(&s.InlCalls)
  1243  		for _, scope := range s.Scopes {
  1244  			for i := 0; i < len(scope.Vars); i++ {
  1245  				_, found := pvars[scope.Vars[i]]
  1246  				if found || !scope.Vars[i].IsInAbstract {
  1247  					continue
  1248  				}
  1249  				flattened = append(flattened, scope.Vars[i])
  1250  			}
  1251  		}
  1252  		if len(flattened) > 0 {
  1253  			slices.SortFunc(flattened, byChildIndexCmp)
  1254  
  1255  			if logDwarf {
  1256  				ctxt.Logf("putAbstractScope(%v): vars:", s.Info)
  1257  				for i, v := range flattened {
  1258  					ctxt.Logf(" %d:%s", i, v.Name)
  1259  				}
  1260  				ctxt.Logf("\n")
  1261  			}
  1262  
  1263  			// This slice will hold the offset in bytes for each child
  1264  			// variable DIE with respect to the start of the parent
  1265  			// subprogram DIE.
  1266  			for _, v := range flattened {
  1267  				offsets = append(offsets, int32(ctxt.CurrentOffset(s.Absfn)))
  1268  				putAbstractVar(ctxt, s.Absfn, v)
  1269  			}
  1270  		}
  1271  	}
  1272  	ctxt.RecordChildDieOffsets(s.Absfn, flattened, offsets)
  1273  
  1274  	Uleb128put(ctxt, s.Absfn, 0)
  1275  	return nil
  1276  }
  1277  
  1278  // dwarfFileIndex returns the DWARF file index value for the file associated
  1279  // with pos.
  1280  func dwarfFileIndex(pos src.Pos) int64 {
  1281  	return int64(1 + pos.FileIndex())
  1282  }
  1283  
  1284  // Emit DWARF attributes and child DIEs for an inlined subroutine. The
  1285  // first attribute of an inlined subroutine DIE is a reference back to
  1286  // its corresponding 'abstract' DIE (containing location-independent
  1287  // attributes such as name, type, etc). Inlined subroutine DIEs can
  1288  // have other inlined subroutine DIEs as children.
  1289  func putInlinedFunc(ctxt Context, s *FnState, callIdx int) error {
  1290  	ic := s.InlCalls.Calls[callIdx]
  1291  	callee := ic.AbsFunSym
  1292  
  1293  	// For DWARF 5, we always use the ranges form of the abbrev, since
  1294  	// it is more compact than using explicit hi/lo PC attrs.  See
  1295  	// issue #72821 for more on why this makes sense.
  1296  	abbrev := DW_ABRV_INLINED_SUBROUTINE_RANGES
  1297  	if len(ic.Ranges) == 1 && !buildcfg.Experiment.Dwarf5 {
  1298  		abbrev = DW_ABRV_INLINED_SUBROUTINE
  1299  	}
  1300  	Uleb128put(ctxt, s.Info, int64(abbrev))
  1301  
  1302  	if logDwarf {
  1303  		ctxt.Logf("putInlinedFunc(callee=%v,abbrev=%d)\n", callee, abbrev)
  1304  	}
  1305  
  1306  	// Abstract origin.
  1307  	putattr(ctxt, s.Info, abbrev, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, callee)
  1308  
  1309  	if abbrev == DW_ABRV_INLINED_SUBROUTINE_RANGES {
  1310  		putattr(ctxt, s.Info, abbrev, DW_FORM_sec_offset, DW_CLS_PTR, ctxt.Size(s.Ranges), s.Ranges)
  1311  		s.PutRanges(ctxt, ic.Ranges)
  1312  	} else {
  1313  		st := ic.Ranges[0].Start
  1314  		en := ic.Ranges[0].End
  1315  		emitHiLoPc(ctxt, abbrev, s, st, en)
  1316  	}
  1317  
  1318  	// Emit call file, line attrs.
  1319  	putattr(ctxt, s.Info, abbrev, DW_FORM_data4, DW_CLS_CONSTANT, dwarfFileIndex(ic.CallPos), nil)
  1320  	form := int(expandPseudoForm(DW_FORM_udata_pseudo))
  1321  	putattr(ctxt, s.Info, abbrev, form, DW_CLS_CONSTANT, int64(ic.CallPos.RelLine()), nil)
  1322  
  1323  	// Variables associated with this inlined routine instance.
  1324  	vars := ic.InlVars
  1325  	slices.SortFunc(vars, byChildIndexCmp)
  1326  	inlIndex := ic.InlIndex
  1327  	var encbuf [20]byte
  1328  	for _, v := range vars {
  1329  		if !v.IsInAbstract {
  1330  			continue
  1331  		}
  1332  		putvar(ctxt, s, v, callee, abbrev, inlIndex, encbuf[:0])
  1333  	}
  1334  
  1335  	// Children of this inline.
  1336  	for _, sib := range inlChildren(callIdx, &s.InlCalls) {
  1337  		err := putInlinedFunc(ctxt, s, sib)
  1338  		if err != nil {
  1339  			return err
  1340  		}
  1341  	}
  1342  
  1343  	Uleb128put(ctxt, s.Info, 0)
  1344  	return nil
  1345  }
  1346  
  1347  func emitHiLoPc(ctxt Context, abbrev int, fns *FnState, st int64, en int64) {
  1348  	if buildcfg.Experiment.Dwarf5 {
  1349  		putattr(ctxt, fns.Info, abbrev, DW_FORM_addrx, DW_CLS_CONSTANT, st, fns.StartPC)
  1350  		putattr(ctxt, fns.Info, abbrev, DW_FORM_udata, DW_CLS_CONSTANT, en, 0)
  1351  	} else {
  1352  		putattr(ctxt, fns.Info, abbrev, DW_FORM_addr, DW_CLS_ADDRESS, st, fns.StartPC)
  1353  		putattr(ctxt, fns.Info, abbrev, DW_FORM_addr, DW_CLS_ADDRESS, en, fns.StartPC)
  1354  	}
  1355  }
  1356  
  1357  // Emit DWARF attributes and child DIEs for a 'concrete' subprogram,
  1358  // meaning the out-of-line copy of a function that was inlined at some
  1359  // point during the compilation of its containing package. The first
  1360  // attribute for a concrete DIE is a reference to the 'abstract' DIE
  1361  // for the function (which holds location-independent attributes such
  1362  // as name, type), then the remainder of the attributes are specific
  1363  // to this instance (location, frame base, etc).
  1364  func PutConcreteFunc(ctxt Context, s *FnState, isWrapper bool, fncount int) error {
  1365  	if logDwarf {
  1366  		ctxt.Logf("PutConcreteFunc(%v)\n", s.Info)
  1367  	}
  1368  	abbrev := DW_ABRV_FUNCTION_CONCRETE
  1369  	if isWrapper {
  1370  		abbrev = DW_ABRV_WRAPPER_CONCRETE
  1371  	}
  1372  	Uleb128put(ctxt, s.Info, int64(abbrev))
  1373  
  1374  	// Abstract origin.
  1375  	putattr(ctxt, s.Info, abbrev, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, s.Absfn)
  1376  
  1377  	// Start/end PC.
  1378  	emitHiLoPc(ctxt, abbrev, s, 0, s.Size)
  1379  
  1380  	// cfa / frame base
  1381  	putattr(ctxt, s.Info, abbrev, DW_FORM_block1, DW_CLS_BLOCK, 1, []byte{DW_OP_call_frame_cfa})
  1382  
  1383  	if isWrapper {
  1384  		putattr(ctxt, s.Info, abbrev, DW_FORM_flag, DW_CLS_FLAG, int64(1), 0)
  1385  	}
  1386  
  1387  	// Scopes
  1388  	if err := putPrunedScopes(ctxt, s, abbrev); err != nil {
  1389  		return err
  1390  	}
  1391  
  1392  	// Inlined subroutines.
  1393  	for _, sib := range inlChildren(-1, &s.InlCalls) {
  1394  		err := putInlinedFunc(ctxt, s, sib)
  1395  		if err != nil {
  1396  			return err
  1397  		}
  1398  	}
  1399  
  1400  	Uleb128put(ctxt, s.Info, 0)
  1401  	return nil
  1402  }
  1403  
  1404  // Emit DWARF attributes and child DIEs for a subprogram. Here
  1405  // 'default' implies that the function in question was not inlined
  1406  // when its containing package was compiled (hence there is no need to
  1407  // emit an abstract version for it to use as a base for inlined
  1408  // routine records).
  1409  func PutDefaultFunc(ctxt Context, s *FnState, isWrapper bool) error {
  1410  	if logDwarf {
  1411  		ctxt.Logf("PutDefaultFunc(%v)\n", s.Info)
  1412  	}
  1413  	abbrev := DW_ABRV_FUNCTION
  1414  	if isWrapper {
  1415  		abbrev = DW_ABRV_WRAPPER
  1416  	}
  1417  	Uleb128put(ctxt, s.Info, int64(abbrev))
  1418  
  1419  	name := s.Name
  1420  	if strings.HasPrefix(name, `"".`) {
  1421  		return fmt.Errorf("unqualified symbol name: %v", name)
  1422  	}
  1423  
  1424  	putattr(ctxt, s.Info, DW_ABRV_FUNCTION, DW_FORM_string, DW_CLS_STRING, int64(len(name)), name)
  1425  	emitHiLoPc(ctxt, abbrev, s, 0, s.Size)
  1426  	putattr(ctxt, s.Info, abbrev, DW_FORM_block1, DW_CLS_BLOCK, 1, []byte{DW_OP_call_frame_cfa})
  1427  	if isWrapper {
  1428  		putattr(ctxt, s.Info, abbrev, DW_FORM_flag, DW_CLS_FLAG, int64(1), 0)
  1429  	} else {
  1430  		putattr(ctxt, s.Info, abbrev, DW_FORM_data4, DW_CLS_CONSTANT, dwarfFileIndex(s.StartPos), nil)
  1431  		putattr(ctxt, s.Info, abbrev, DW_FORM_udata, DW_CLS_CONSTANT, int64(s.StartPos.RelLine()), nil)
  1432  
  1433  		var ev int64
  1434  		if s.External {
  1435  			ev = 1
  1436  		}
  1437  		putattr(ctxt, s.Info, abbrev, DW_FORM_flag, DW_CLS_FLAG, ev, 0)
  1438  	}
  1439  
  1440  	// Scopes
  1441  	if err := putPrunedScopes(ctxt, s, abbrev); err != nil {
  1442  		return err
  1443  	}
  1444  
  1445  	// Inlined subroutines.
  1446  	for _, sib := range inlChildren(-1, &s.InlCalls) {
  1447  		err := putInlinedFunc(ctxt, s, sib)
  1448  		if err != nil {
  1449  			return err
  1450  		}
  1451  	}
  1452  
  1453  	Uleb128put(ctxt, s.Info, 0)
  1454  	return nil
  1455  }
  1456  
  1457  // putparamtypes writes typedef DIEs for any parametric types that are used by this function.
  1458  func putparamtypes(ctxt Context, s *FnState, scopes []Scope, fnabbrev int) []int64 {
  1459  	if fnabbrev == DW_ABRV_FUNCTION_CONCRETE {
  1460  		return nil
  1461  	}
  1462  
  1463  	maxDictIndex := uint16(0)
  1464  
  1465  	for i := range scopes {
  1466  		for _, v := range scopes[i].Vars {
  1467  			if v.DictIndex > maxDictIndex {
  1468  				maxDictIndex = v.DictIndex
  1469  			}
  1470  		}
  1471  	}
  1472  
  1473  	if maxDictIndex == 0 {
  1474  		return nil
  1475  	}
  1476  
  1477  	dictIndexToOffset := make([]int64, maxDictIndex)
  1478  
  1479  	for i := range scopes {
  1480  		for _, v := range scopes[i].Vars {
  1481  			if v.DictIndex == 0 || dictIndexToOffset[v.DictIndex-1] != 0 {
  1482  				continue
  1483  			}
  1484  
  1485  			dictIndexToOffset[v.DictIndex-1] = ctxt.CurrentOffset(s.Info)
  1486  
  1487  			Uleb128put(ctxt, s.Info, int64(DW_ABRV_DICT_INDEX))
  1488  			n := fmt.Sprintf(".param%d", v.DictIndex-1)
  1489  			putattr(ctxt, s.Info, DW_ABRV_DICT_INDEX, DW_FORM_string, DW_CLS_STRING, int64(len(n)), n)
  1490  			putattr(ctxt, s.Info, DW_ABRV_DICT_INDEX, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, v.Type)
  1491  			putattr(ctxt, s.Info, DW_ABRV_DICT_INDEX, DW_FORM_udata, DW_CLS_CONSTANT, int64(v.DictIndex-1), nil)
  1492  		}
  1493  	}
  1494  
  1495  	return dictIndexToOffset
  1496  }
  1497  
  1498  func putscope(ctxt Context, s *FnState, scopes []Scope, curscope int32, fnabbrev int, encbuf []byte) int32 {
  1499  
  1500  	if logDwarf {
  1501  		ctxt.Logf("putscope(%v,%d): vars:", s.Info, curscope)
  1502  		for i, v := range scopes[curscope].Vars {
  1503  			ctxt.Logf(" %d:%d:%s", i, v.ChildIndex, v.Name)
  1504  		}
  1505  		ctxt.Logf("\n")
  1506  	}
  1507  
  1508  	for _, v := range scopes[curscope].Vars {
  1509  		putvar(ctxt, s, v, s.Absfn, fnabbrev, -1, encbuf)
  1510  	}
  1511  	this := curscope
  1512  	curscope++
  1513  	for curscope < int32(len(scopes)) {
  1514  		scope := scopes[curscope]
  1515  		if scope.Parent != this {
  1516  			return curscope
  1517  		}
  1518  
  1519  		if len(scopes[curscope].Vars) == 0 {
  1520  			curscope = putscope(ctxt, s, scopes, curscope, fnabbrev, encbuf)
  1521  			continue
  1522  		}
  1523  
  1524  		// For DWARF 5, we always use the ranges form of the abbrev, since
  1525  		// it is more compact than using explicit hi/lo PC attrs.  See
  1526  		// issue #72821 for more on why this makes sense.
  1527  		if len(scope.Ranges) == 1 && !buildcfg.Experiment.Dwarf5 {
  1528  			Uleb128put(ctxt, s.Info, DW_ABRV_LEXICAL_BLOCK_SIMPLE)
  1529  			putattr(ctxt, s.Info, DW_ABRV_LEXICAL_BLOCK_SIMPLE, DW_FORM_addr, DW_CLS_ADDRESS, scope.Ranges[0].Start, s.StartPC)
  1530  			putattr(ctxt, s.Info, DW_ABRV_LEXICAL_BLOCK_SIMPLE, DW_FORM_addr, DW_CLS_ADDRESS, scope.Ranges[0].End, s.StartPC)
  1531  		} else {
  1532  			Uleb128put(ctxt, s.Info, DW_ABRV_LEXICAL_BLOCK_RANGES)
  1533  			putattr(ctxt, s.Info, DW_ABRV_LEXICAL_BLOCK_RANGES, DW_FORM_sec_offset, DW_CLS_PTR, ctxt.Size(s.Ranges), s.Ranges)
  1534  
  1535  			s.PutRanges(ctxt, scope.Ranges)
  1536  		}
  1537  
  1538  		curscope = putscope(ctxt, s, scopes, curscope, fnabbrev, encbuf)
  1539  
  1540  		Uleb128put(ctxt, s.Info, 0)
  1541  	}
  1542  	return curscope
  1543  }
  1544  
  1545  func concreteVar(fnabbrev int, v *Var) bool {
  1546  	concrete := true
  1547  	switch fnabbrev {
  1548  	case DW_ABRV_FUNCTION, DW_ABRV_WRAPPER:
  1549  		concrete = false
  1550  	case DW_ABRV_FUNCTION_CONCRETE, DW_ABRV_WRAPPER_CONCRETE:
  1551  		// If we're emitting a concrete subprogram DIE and the variable
  1552  		// in question is not part of the corresponding abstract function DIE,
  1553  		// then use the default (non-concrete) abbrev for this param.
  1554  		if !v.IsInAbstract {
  1555  			concrete = false
  1556  		}
  1557  	case DW_ABRV_INLINED_SUBROUTINE, DW_ABRV_INLINED_SUBROUTINE_RANGES:
  1558  	default:
  1559  		panic("should never happen")
  1560  	}
  1561  	return concrete
  1562  }
  1563  
  1564  // Emit DWARF attributes for a variable belonging to an 'abstract' subprogram.
  1565  func putAbstractVar(ctxt Context, info Sym, v *Var) {
  1566  	// The contents of this functions are used to generate putAbstractVarAbbrev automatically, see TestPutVarAbbrevGenerator.
  1567  	abbrev := putAbstractVarAbbrev(v)
  1568  	Uleb128put(ctxt, info, int64(abbrev))
  1569  	putattr(ctxt, info, abbrev, DW_FORM_string, DW_CLS_STRING, int64(len(v.Name)), v.Name) // DW_AT_name
  1570  
  1571  	// Isreturn attribute if this is a param
  1572  	if v.Tag == DW_TAG_formal_parameter {
  1573  		var isReturn int64
  1574  		if v.IsReturnValue {
  1575  			isReturn = 1
  1576  		}
  1577  		putattr(ctxt, info, abbrev, DW_FORM_flag, DW_CLS_FLAG, isReturn, nil) // DW_AT_variable_parameter
  1578  	}
  1579  
  1580  	// Line
  1581  	if v.Tag == DW_TAG_variable {
  1582  		// See issue 23374 for more on why decl line is skipped for abs params.
  1583  		putattr(ctxt, info, abbrev, DW_FORM_udata, DW_CLS_CONSTANT, int64(v.DeclLine), nil) // DW_AT_decl_line
  1584  	}
  1585  
  1586  	// Type
  1587  	putattr(ctxt, info, abbrev, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, v.Type) // DW_AT_type
  1588  
  1589  	// Var has no children => no terminator
  1590  }
  1591  
  1592  func putvar(ctxt Context, s *FnState, v *Var, absfn Sym, fnabbrev, inlIndex int, encbuf []byte) {
  1593  	// The contents of this functions are used to generate putvarAbbrev automatically, see TestPutVarAbbrevGenerator.
  1594  	concrete := concreteVar(fnabbrev, v)
  1595  	hasParametricType := !concrete && (v.DictIndex > 0 && s.dictIndexToOffset != nil && s.dictIndexToOffset[v.DictIndex-1] != 0)
  1596  	withLoclist := v.WithLoclist && v.PutLocationList != nil
  1597  
  1598  	abbrev := putvarAbbrev(v, concrete, withLoclist)
  1599  	Uleb128put(ctxt, s.Info, int64(abbrev))
  1600  
  1601  	// Abstract origin for concrete / inlined case
  1602  	if concrete {
  1603  		// Here we are making a reference to a child DIE of an abstract
  1604  		// function subprogram DIE. The child DIE has no LSym, so instead
  1605  		// after the call to 'putattr' below we make a call to register
  1606  		// the child DIE reference.
  1607  		putattr(ctxt, s.Info, abbrev, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, absfn) // DW_AT_abstract_origin
  1608  		ctxt.RecordDclReference(s.Info, absfn, int(v.ChildIndex), inlIndex)
  1609  	} else {
  1610  		// Var name, line for abstract and default cases
  1611  		n := v.Name
  1612  		putattr(ctxt, s.Info, abbrev, DW_FORM_string, DW_CLS_STRING, int64(len(n)), n) // DW_AT_name
  1613  		if v.Tag == DW_TAG_formal_parameter {
  1614  			var isReturn int64
  1615  			if v.IsReturnValue {
  1616  				isReturn = 1
  1617  			}
  1618  			putattr(ctxt, s.Info, abbrev, DW_FORM_flag, DW_CLS_FLAG, isReturn, nil) // DW_AT_variable_parameter
  1619  		}
  1620  		putattr(ctxt, s.Info, abbrev, DW_FORM_udata, DW_CLS_CONSTANT, int64(v.DeclLine), nil) // DW_AT_decl_line
  1621  		if hasParametricType {
  1622  			// If the type of this variable is parametric use the entry emitted by putparamtypes
  1623  			putattr(ctxt, s.Info, abbrev, DW_FORM_ref_addr, DW_CLS_REFERENCE, s.dictIndexToOffset[v.DictIndex-1], s.Info) // DW_AT_type
  1624  		} else {
  1625  			putattr(ctxt, s.Info, abbrev, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, v.Type) // DW_AT_type
  1626  		}
  1627  
  1628  		if v.ClosureOffset > 0 {
  1629  			putattr(ctxt, s.Info, abbrev, DW_FORM_udata, DW_CLS_CONSTANT, v.ClosureOffset, nil) // DW_AT_go_closure_offset
  1630  		}
  1631  	}
  1632  
  1633  	if withLoclist {
  1634  		putattr(ctxt, s.Info, abbrev, DW_FORM_sec_offset, DW_CLS_PTR, ctxt.Size(s.Loc), s.Loc) // DW_AT_location
  1635  		v.PutLocationList(s.Loc, s.StartPC)
  1636  	} else {
  1637  		loc := encbuf[:0]
  1638  		switch {
  1639  		case v.WithLoclist:
  1640  			break // no location
  1641  		case v.StackOffset == 0:
  1642  			loc = append(loc, DW_OP_call_frame_cfa)
  1643  		default:
  1644  			loc = append(loc, DW_OP_fbreg)
  1645  			loc = AppendSleb128(loc, int64(v.StackOffset))
  1646  		}
  1647  		putattr(ctxt, s.Info, abbrev, DW_FORM_block1, DW_CLS_BLOCK, int64(len(loc)), loc) // DW_AT_location
  1648  	}
  1649  
  1650  	// Var has no children => no terminator
  1651  }
  1652  
  1653  // byChildIndexCmp compares two *dwarf.Var by child index.
  1654  func byChildIndexCmp(a, b *Var) int { return cmp.Compare(a.ChildIndex, b.ChildIndex) }
  1655  
  1656  // IsDWARFEnabledOnAIXLd returns true if DWARF is possible on the
  1657  // current extld.
  1658  // AIX ld doesn't support DWARF with -bnoobjreorder with version
  1659  // prior to 7.2.2.
  1660  func IsDWARFEnabledOnAIXLd(extld []string) (bool, error) {
  1661  	name, args := extld[0], extld[1:]
  1662  	args = append(args, "-Wl,-V")
  1663  	out, err := exec.Command(name, args...).CombinedOutput()
  1664  	if err != nil {
  1665  		// The normal output should display ld version and
  1666  		// then fails because ".main" is not defined:
  1667  		// ld: 0711-317 ERROR: Undefined symbol: .main
  1668  		if !bytes.Contains(out, []byte("0711-317")) {
  1669  			return false, fmt.Errorf("%s -Wl,-V failed: %v\n%s", extld, err, out)
  1670  		}
  1671  	}
  1672  	// gcc -Wl,-V output should be:
  1673  	//   /usr/bin/ld: LD X.X.X(date)
  1674  	//   ...
  1675  	out = bytes.TrimPrefix(out, []byte("/usr/bin/ld: LD "))
  1676  	vers := string(bytes.Split(out, []byte("("))[0])
  1677  	subvers := strings.Split(vers, ".")
  1678  	if len(subvers) != 3 {
  1679  		return false, fmt.Errorf("cannot parse %s -Wl,-V (%s): %v\n", extld, out, err)
  1680  	}
  1681  	if v, err := strconv.Atoi(subvers[0]); err != nil || v < 7 {
  1682  		return false, nil
  1683  	} else if v > 7 {
  1684  		return true, nil
  1685  	}
  1686  	if v, err := strconv.Atoi(subvers[1]); err != nil || v < 2 {
  1687  		return false, nil
  1688  	} else if v > 2 {
  1689  		return true, nil
  1690  	}
  1691  	if v, err := strconv.Atoi(subvers[2]); err != nil || v < 2 {
  1692  		return false, nil
  1693  	}
  1694  	return true, nil
  1695  }
  1696  

View as plain text