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 interface {
    44  }
    45  
    46  // A Var represents a local variable or a function parameter.
    47  type Var struct {
    48  	Name          string
    49  	Tag           int // Either DW_TAG_variable or DW_TAG_formal_parameter
    50  	WithLoclist   bool
    51  	IsReturnValue bool
    52  	IsInlFormal   bool
    53  	DictIndex     uint16 // index of the dictionary entry describing the type of this variable
    54  	StackOffset   int32
    55  	// This package can't use the ssa package, so it can't mention ssa.FuncDebug,
    56  	// so indirect through a closure.
    57  	PutLocationList func(listSym, startPC Sym)
    58  	Scope           int32
    59  	Type            Sym
    60  	DeclFile        string
    61  	DeclLine        uint
    62  	DeclCol         uint
    63  	InlIndex        int32 // subtract 1 to form real index into InlTree
    64  	ChildIndex      int32 // child DIE index in abstract function
    65  	IsInAbstract    bool  // variable exists in abstract function
    66  	ClosureOffset   int64 // if non-zero this is the offset of this variable in the closure struct
    67  }
    68  
    69  // A Scope represents a lexical scope. All variables declared within a
    70  // scope will only be visible to instructions covered by the scope.
    71  // Lexical scopes are contiguous in source files but can end up being
    72  // compiled to discontiguous blocks of instructions in the executable.
    73  // The Ranges field lists all the blocks of instructions that belong
    74  // in this scope.
    75  type Scope struct {
    76  	Parent int32
    77  	Ranges []Range
    78  	Vars   []*Var
    79  }
    80  
    81  // A Range represents a half-open interval [Start, End).
    82  type Range struct {
    83  	Start, End int64
    84  }
    85  
    86  // This container is used by the PutFunc* variants below when
    87  // creating the DWARF subprogram DIE(s) for a function.
    88  type FnState struct {
    89  	Name          string
    90  	Info          Sym
    91  	Loc           Sym
    92  	Ranges        Sym
    93  	Absfn         Sym
    94  	StartPC       Sym
    95  	StartPos      src.Pos
    96  	Size          int64
    97  	External      bool
    98  	Scopes        []Scope
    99  	InlCalls      InlCalls
   100  	UseBASEntries bool
   101  
   102  	dictIndexToOffset []int64
   103  }
   104  
   105  func EnableLogging(doit bool) {
   106  	logDwarf = doit
   107  }
   108  
   109  // MergeRanges creates a new range list by merging the ranges from
   110  // its two arguments, then returns the new list.
   111  func MergeRanges(in1, in2 []Range) []Range {
   112  	out := make([]Range, 0, len(in1)+len(in2))
   113  	i, j := 0, 0
   114  	for {
   115  		var cur Range
   116  		if i < len(in2) && j < len(in1) {
   117  			if in2[i].Start < in1[j].Start {
   118  				cur = in2[i]
   119  				i++
   120  			} else {
   121  				cur = in1[j]
   122  				j++
   123  			}
   124  		} else if i < len(in2) {
   125  			cur = in2[i]
   126  			i++
   127  		} else if j < len(in1) {
   128  			cur = in1[j]
   129  			j++
   130  		} else {
   131  			break
   132  		}
   133  
   134  		if n := len(out); n > 0 && cur.Start <= out[n-1].End {
   135  			out[n-1].End = cur.End
   136  		} else {
   137  			out = append(out, cur)
   138  		}
   139  	}
   140  
   141  	return out
   142  }
   143  
   144  // UnifyRanges merges the ranges from 'c' into the list of ranges for 's'.
   145  func (s *Scope) UnifyRanges(c *Scope) {
   146  	s.Ranges = MergeRanges(s.Ranges, c.Ranges)
   147  }
   148  
   149  // AppendRange adds r to s, if r is non-empty.
   150  // If possible, it extends the last Range in s.Ranges; if not, it creates a new one.
   151  func (s *Scope) AppendRange(r Range) {
   152  	if r.End <= r.Start {
   153  		return
   154  	}
   155  	i := len(s.Ranges)
   156  	if i > 0 && s.Ranges[i-1].End == r.Start {
   157  		s.Ranges[i-1].End = r.End
   158  		return
   159  	}
   160  	s.Ranges = append(s.Ranges, r)
   161  }
   162  
   163  type InlCalls struct {
   164  	Calls []InlCall
   165  }
   166  
   167  type InlCall struct {
   168  	// index into ctx.InlTree describing the call inlined here
   169  	InlIndex int
   170  
   171  	// Position of the inlined call site.
   172  	CallPos src.Pos
   173  
   174  	// Dwarf abstract subroutine symbol (really *obj.LSym).
   175  	AbsFunSym Sym
   176  
   177  	// Indices of child inlines within Calls array above.
   178  	Children []int
   179  
   180  	// entries in this list are PAUTO's created by the inliner to
   181  	// capture the promoted formals and locals of the inlined callee.
   182  	InlVars []*Var
   183  
   184  	// PC ranges for this inlined call.
   185  	Ranges []Range
   186  
   187  	// Root call (not a child of some other call).
   188  	Root bool
   189  }
   190  
   191  // A Context specifies how to add data to a Sym.
   192  type Context interface {
   193  	PtrSize() int
   194  	Size(s Sym) int64
   195  	AddInt(s Sym, size int, i int64)
   196  	AddBytes(s Sym, b []byte)
   197  	AddAddress(s Sym, t interface{}, ofs int64)
   198  	AddCURelativeAddress(s Sym, t interface{}, ofs int64)
   199  	AddSectionOffset(s Sym, size int, t interface{}, ofs int64)
   200  	AddDWARFAddrSectionOffset(s Sym, t interface{}, ofs int64)
   201  	AddIndirectTextRef(s Sym, t interface{})
   202  	CurrentOffset(s Sym) int64
   203  	RecordDclReference(from Sym, to Sym, dclIdx int, inlIndex int)
   204  	RecordChildDieOffsets(s Sym, vars []*Var, offsets []int32)
   205  	AddString(s Sym, v string)
   206  	Logf(format string, args ...interface{})
   207  }
   208  
   209  // AppendUleb128 appends v to b using DWARF's unsigned LEB128 encoding.
   210  func AppendUleb128(b []byte, v uint64) []byte {
   211  	for {
   212  		c := uint8(v & 0x7f)
   213  		v >>= 7
   214  		if v != 0 {
   215  			c |= 0x80
   216  		}
   217  		b = append(b, c)
   218  		if c&0x80 == 0 {
   219  			break
   220  		}
   221  	}
   222  	return b
   223  }
   224  
   225  // AppendSleb128 appends v to b using DWARF's signed LEB128 encoding.
   226  func AppendSleb128(b []byte, v int64) []byte {
   227  	for {
   228  		c := uint8(v & 0x7f)
   229  		s := uint8(v & 0x40)
   230  		v >>= 7
   231  		if (v != -1 || s == 0) && (v != 0 || s != 0) {
   232  			c |= 0x80
   233  		}
   234  		b = append(b, c)
   235  		if c&0x80 == 0 {
   236  			break
   237  		}
   238  	}
   239  	return b
   240  }
   241  
   242  // sevenbits contains all unsigned seven bit numbers, indexed by their value.
   243  var sevenbits = [...]byte{
   244  	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
   245  	0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
   246  	0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
   247  	0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
   248  	0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
   249  	0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
   250  	0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
   251  	0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
   252  }
   253  
   254  // sevenBitU returns the unsigned LEB128 encoding of v if v is seven bits and nil otherwise.
   255  // The contents of the returned slice must not be modified.
   256  func sevenBitU(v int64) []byte {
   257  	if uint64(v) < uint64(len(sevenbits)) {
   258  		return sevenbits[v : v+1]
   259  	}
   260  	return nil
   261  }
   262  
   263  // sevenBitS returns the signed LEB128 encoding of v if v is seven bits and nil otherwise.
   264  // The contents of the returned slice must not be modified.
   265  func sevenBitS(v int64) []byte {
   266  	if uint64(v) <= 63 {
   267  		return sevenbits[v : v+1]
   268  	}
   269  	if uint64(-v) <= 64 {
   270  		return sevenbits[128+v : 128+v+1]
   271  	}
   272  	return nil
   273  }
   274  
   275  // Uleb128put appends v to s using DWARF's unsigned LEB128 encoding.
   276  func Uleb128put(ctxt Context, s Sym, v int64) {
   277  	b := sevenBitU(v)
   278  	if b == nil {
   279  		var encbuf [20]byte
   280  		b = AppendUleb128(encbuf[:0], uint64(v))
   281  	}
   282  	ctxt.AddBytes(s, b)
   283  }
   284  
   285  // Sleb128put appends v to s using DWARF's signed LEB128 encoding.
   286  func Sleb128put(ctxt Context, s Sym, v int64) {
   287  	b := sevenBitS(v)
   288  	if b == nil {
   289  		var encbuf [20]byte
   290  		b = AppendSleb128(encbuf[:0], v)
   291  	}
   292  	ctxt.AddBytes(s, b)
   293  }
   294  
   295  /*
   296   * Defining Abbrevs. This is hardcoded on a per-platform basis (that is,
   297   * each platform will see a fixed abbrev table for all objects); the number
   298   * of abbrev entries is fairly small (compared to C++ objects).  The DWARF
   299   * spec places no restriction on the ordering of attributes in the
   300   * Abbrevs and DIEs, and we will always write them out in the order
   301   * of declaration in the abbrev.
   302   */
   303  type dwAttrForm struct {
   304  	attr uint16
   305  	form uint8
   306  }
   307  
   308  // Go-specific type attributes.
   309  const (
   310  	DW_AT_go_kind = 0x2900
   311  	DW_AT_go_key  = 0x2901
   312  	DW_AT_go_elem = 0x2902
   313  	// Attribute for DW_TAG_member of a struct type.
   314  	// Nonzero value indicates the struct field is an embedded field.
   315  	DW_AT_go_embedded_field = 0x2903
   316  	DW_AT_go_runtime_type   = 0x2904
   317  
   318  	DW_AT_go_package_name   = 0x2905 // Attribute for DW_TAG_compile_unit
   319  	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
   320  	DW_AT_go_closure_offset = 0x2907 // Attribute for DW_TAG_variable, offset in the closure struct where this captured variable resides
   321  
   322  	DW_AT_internal_location = 253 // params and locals; not emitted
   323  )
   324  
   325  // Index into the abbrevs table below.
   326  const (
   327  	DW_ABRV_NULL = iota
   328  	DW_ABRV_COMPUNIT
   329  	DW_ABRV_COMPUNIT_TEXTLESS
   330  	DW_ABRV_FUNCTION
   331  	DW_ABRV_WRAPPER
   332  	DW_ABRV_FUNCTION_ABSTRACT
   333  	DW_ABRV_FUNCTION_CONCRETE
   334  	DW_ABRV_WRAPPER_CONCRETE
   335  	DW_ABRV_INLINED_SUBROUTINE
   336  	DW_ABRV_INLINED_SUBROUTINE_RANGES
   337  	DW_ABRV_VARIABLE
   338  	DW_ABRV_INT_CONSTANT
   339  	DW_ABRV_LEXICAL_BLOCK_RANGES
   340  	DW_ABRV_LEXICAL_BLOCK_SIMPLE
   341  	DW_ABRV_STRUCTFIELD
   342  	DW_ABRV_FUNCTYPEPARAM
   343  	DW_ABRV_FUNCTYPEOUTPARAM
   344  	DW_ABRV_DOTDOTDOT
   345  	DW_ABRV_ARRAYRANGE
   346  	DW_ABRV_NULLTYPE
   347  	DW_ABRV_BASETYPE
   348  	DW_ABRV_ARRAYTYPE
   349  	DW_ABRV_CHANTYPE
   350  	DW_ABRV_FUNCTYPE
   351  	DW_ABRV_IFACETYPE
   352  	DW_ABRV_MAPTYPE
   353  	DW_ABRV_PTRTYPE
   354  	DW_ABRV_BARE_PTRTYPE // only for void*, no DW_AT_type attr to please gdb 6.
   355  	DW_ABRV_SLICETYPE
   356  	DW_ABRV_STRINGTYPE
   357  	DW_ABRV_STRUCTTYPE
   358  	DW_ABRV_TYPEDECL
   359  	DW_ABRV_DICT_INDEX
   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  
   844  // GetAbbrev returns the contents of the .debug_abbrev section.
   845  func GetAbbrev() []byte {
   846  	abbrevs := Abbrevs()
   847  	var buf []byte
   848  	for i := 1; i < len(abbrevs); i++ {
   849  		// See section 7.5.3
   850  		buf = AppendUleb128(buf, uint64(i))
   851  		buf = AppendUleb128(buf, uint64(abbrevs[i].tag))
   852  		buf = append(buf, abbrevs[i].children)
   853  		for _, f := range abbrevs[i].attr {
   854  			buf = AppendUleb128(buf, uint64(f.attr))
   855  			buf = AppendUleb128(buf, uint64(f.form))
   856  		}
   857  		buf = append(buf, 0, 0)
   858  	}
   859  	return append(buf, 0)
   860  }
   861  
   862  /*
   863   * Debugging Information Entries and their attributes.
   864   */
   865  
   866  // DWAttr represents an attribute of a DWDie.
   867  //
   868  // For DW_CLS_string and _block, value should contain the length, and
   869  // data the data, for _reference, value is 0 and data is a DWDie* to
   870  // the referenced instance, for all others, value is the whole thing
   871  // and data is null.
   872  type DWAttr struct {
   873  	Link  *DWAttr
   874  	Atr   uint16 // DW_AT_
   875  	Cls   uint8  // DW_CLS_
   876  	Value int64
   877  	Data  interface{}
   878  }
   879  
   880  // DWDie represents a DWARF debug info entry.
   881  type DWDie struct {
   882  	Abbrev int
   883  	Link   *DWDie
   884  	Child  *DWDie
   885  	Attr   *DWAttr
   886  	Sym    Sym
   887  }
   888  
   889  func putattr(ctxt Context, s Sym, abbrev int, form int, cls int, value int64, data interface{}) error {
   890  	switch form {
   891  	case DW_FORM_addr: // address
   892  		// Allow nil addresses for DW_AT_go_runtime_type.
   893  		if data == nil && value == 0 {
   894  			ctxt.AddInt(s, ctxt.PtrSize(), 0)
   895  			break
   896  		}
   897  		if cls == DW_CLS_GO_TYPEREF {
   898  			ctxt.AddSectionOffset(s, ctxt.PtrSize(), data, value)
   899  			break
   900  		}
   901  		ctxt.AddAddress(s, data, value)
   902  
   903  	case DW_FORM_block1: // block
   904  		if cls == DW_CLS_ADDRESS {
   905  			ctxt.AddInt(s, 1, int64(1+ctxt.PtrSize()))
   906  			ctxt.AddInt(s, 1, DW_OP_addr)
   907  			ctxt.AddAddress(s, data, 0)
   908  			break
   909  		}
   910  
   911  		value &= 0xff
   912  		ctxt.AddInt(s, 1, value)
   913  		p := data.([]byte)[:value]
   914  		ctxt.AddBytes(s, p)
   915  
   916  	case DW_FORM_block2: // block
   917  		value &= 0xffff
   918  
   919  		ctxt.AddInt(s, 2, value)
   920  		p := data.([]byte)[:value]
   921  		ctxt.AddBytes(s, p)
   922  
   923  	case DW_FORM_block4: // block
   924  		value &= 0xffffffff
   925  
   926  		ctxt.AddInt(s, 4, value)
   927  		p := data.([]byte)[:value]
   928  		ctxt.AddBytes(s, p)
   929  
   930  	case DW_FORM_block: // block
   931  		Uleb128put(ctxt, s, value)
   932  
   933  		p := data.([]byte)[:value]
   934  		ctxt.AddBytes(s, p)
   935  
   936  	case DW_FORM_data1: // constant
   937  		ctxt.AddInt(s, 1, value)
   938  
   939  	case DW_FORM_data2: // constant
   940  		ctxt.AddInt(s, 2, value)
   941  
   942  	case DW_FORM_data4: // constant, {line,loclist,mac,rangelist}ptr
   943  		if cls == DW_CLS_PTR { // DW_AT_stmt_list and DW_AT_ranges
   944  			ctxt.AddDWARFAddrSectionOffset(s, data, value)
   945  			break
   946  		}
   947  		ctxt.AddInt(s, 4, value)
   948  
   949  	case DW_FORM_data8: // constant, {line,loclist,mac,rangelist}ptr
   950  		ctxt.AddInt(s, 8, value)
   951  
   952  	case DW_FORM_sdata: // constant
   953  		Sleb128put(ctxt, s, value)
   954  
   955  	case DW_FORM_udata: // constant
   956  		Uleb128put(ctxt, s, value)
   957  
   958  	case DW_FORM_string: // string
   959  		str := data.(string)
   960  		ctxt.AddString(s, str)
   961  		// TODO(ribrdb): verify padded strings are never used and remove this
   962  		for i := int64(len(str)); i < value; i++ {
   963  			ctxt.AddInt(s, 1, 0)
   964  		}
   965  
   966  	case DW_FORM_flag: // flag
   967  		if value != 0 {
   968  			ctxt.AddInt(s, 1, 1)
   969  		} else {
   970  			ctxt.AddInt(s, 1, 0)
   971  		}
   972  
   973  	// As of DWARF 3 the ref_addr is always 32 bits, unless emitting a large
   974  	// (> 4 GB of debug info aka "64-bit") unit, which we don't implement.
   975  	case DW_FORM_ref_addr: // reference to a DIE in the .info section
   976  		fallthrough
   977  	case DW_FORM_sec_offset: // offset into a DWARF section other than .info
   978  		if data == nil {
   979  			return fmt.Errorf("dwarf: null reference in %d", abbrev)
   980  		}
   981  		ctxt.AddDWARFAddrSectionOffset(s, data, value)
   982  
   983  	case DW_FORM_addrx: // index into .debug_addr section
   984  		ctxt.AddIndirectTextRef(s, data)
   985  
   986  	case DW_FORM_ref1, // reference within the compilation unit
   987  		DW_FORM_ref2,      // reference
   988  		DW_FORM_ref4,      // reference
   989  		DW_FORM_ref8,      // reference
   990  		DW_FORM_ref_udata, // reference
   991  
   992  		DW_FORM_strp,     // string
   993  		DW_FORM_indirect: // (see Section 7.5.3)
   994  		fallthrough
   995  	default:
   996  		return fmt.Errorf("dwarf: unsupported attribute form %d / class %d", form, cls)
   997  	}
   998  	return nil
   999  }
  1000  
  1001  // PutAttrs writes the attributes for a DIE to symbol 's'.
  1002  //
  1003  // Note that we can (and do) add arbitrary attributes to a DIE, but
  1004  // only the ones actually listed in the Abbrev will be written out.
  1005  func PutAttrs(ctxt Context, s Sym, abbrev int, attr *DWAttr) {
  1006  	abbrevs := Abbrevs()
  1007  Outer:
  1008  	for _, f := range abbrevs[abbrev].attr {
  1009  		for ap := attr; ap != nil; ap = ap.Link {
  1010  			if ap.Atr == f.attr {
  1011  				putattr(ctxt, s, abbrev, int(f.form), int(ap.Cls), ap.Value, ap.Data)
  1012  				continue Outer
  1013  			}
  1014  		}
  1015  
  1016  		putattr(ctxt, s, abbrev, int(f.form), 0, 0, nil)
  1017  	}
  1018  }
  1019  
  1020  // HasChildren reports whether 'die' uses an abbrev that supports children.
  1021  func HasChildren(die *DWDie) bool {
  1022  	abbrevs := Abbrevs()
  1023  	return abbrevs[die.Abbrev].children != 0
  1024  }
  1025  
  1026  // PutIntConst writes a DIE for an integer constant
  1027  func PutIntConst(ctxt Context, info, typ Sym, name string, val int64) {
  1028  	Uleb128put(ctxt, info, DW_ABRV_INT_CONSTANT)
  1029  	putattr(ctxt, info, DW_ABRV_INT_CONSTANT, DW_FORM_string, DW_CLS_STRING, int64(len(name)), name)
  1030  	putattr(ctxt, info, DW_ABRV_INT_CONSTANT, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, typ)
  1031  	putattr(ctxt, info, DW_ABRV_INT_CONSTANT, DW_FORM_sdata, DW_CLS_CONSTANT, val, nil)
  1032  }
  1033  
  1034  // PutGlobal writes a DIE for a global variable.
  1035  func PutGlobal(ctxt Context, info, typ, gvar Sym, name string) {
  1036  	Uleb128put(ctxt, info, DW_ABRV_VARIABLE)
  1037  	putattr(ctxt, info, DW_ABRV_VARIABLE, DW_FORM_string, DW_CLS_STRING, int64(len(name)), name)
  1038  	putattr(ctxt, info, DW_ABRV_VARIABLE, DW_FORM_block1, DW_CLS_ADDRESS, 0, gvar)
  1039  	putattr(ctxt, info, DW_ABRV_VARIABLE, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, typ)
  1040  	putattr(ctxt, info, DW_ABRV_VARIABLE, DW_FORM_flag, DW_CLS_FLAG, 1, nil)
  1041  }
  1042  
  1043  // PutBasedRanges writes a range table to sym. All addresses in ranges are
  1044  // relative to some base address, which must be arranged by the caller
  1045  // (e.g., with a DW_AT_low_pc attribute, or in a BASE-prefixed range).
  1046  func PutBasedRanges(ctxt Context, sym Sym, ranges []Range) {
  1047  	ps := ctxt.PtrSize()
  1048  	// Write ranges.
  1049  	for _, r := range ranges {
  1050  		ctxt.AddInt(sym, ps, r.Start)
  1051  		ctxt.AddInt(sym, ps, r.End)
  1052  	}
  1053  	// Write trailer.
  1054  	ctxt.AddInt(sym, ps, 0)
  1055  	ctxt.AddInt(sym, ps, 0)
  1056  }
  1057  
  1058  // PutRngListRanges writes a DWARF5-style set of rangelist entries to sym,
  1059  // using base as a starting/base address.
  1060  func PutRngListRanges(ctxt Context, sym Sym, base Sym, ranges []Range) {
  1061  	addULEB128 := func(v int64) {
  1062  		b := sevenBitU(v)
  1063  		if b == nil {
  1064  			var encbuf [20]byte
  1065  			b = AppendUleb128(encbuf[:0], uint64(v))
  1066  		}
  1067  		ctxt.AddBytes(sym, b)
  1068  	}
  1069  	// First entry is base address.
  1070  	ctxt.AddInt(sym, 1, DW_RLE_base_addressx)
  1071  	ctxt.AddIndirectTextRef(sym, base)
  1072  	// Remaining entries are .debug_rnglist offset pairs
  1073  	for _, r := range ranges {
  1074  		ctxt.AddInt(sym, 1, DW_RLE_offset_pair)
  1075  		addULEB128(r.Start)
  1076  		addULEB128(r.End)
  1077  	}
  1078  	// Terminator to mark end of list
  1079  	ctxt.AddInt(sym, 1, DW_RLE_end_of_list)
  1080  }
  1081  
  1082  // PutRanges writes a range table to s.Ranges.
  1083  // All addresses in ranges are relative to s.base.
  1084  func (s *FnState) PutRanges(ctxt Context, ranges []Range) {
  1085  	ps := ctxt.PtrSize()
  1086  	sym, base := s.Ranges, s.StartPC
  1087  
  1088  	if buildcfg.Experiment.Dwarf5 {
  1089  		PutRngListRanges(ctxt, sym, base, ranges)
  1090  		return
  1091  	}
  1092  
  1093  	if s.UseBASEntries {
  1094  		// Using a Base Address Selection Entry reduces the number of relocations, but
  1095  		// this is not done on macOS because it is not supported by dsymutil/dwarfdump/lldb
  1096  		ctxt.AddInt(sym, ps, -1)
  1097  		ctxt.AddAddress(sym, base, 0)
  1098  		PutBasedRanges(ctxt, sym, ranges)
  1099  		return
  1100  	}
  1101  
  1102  	// Write ranges full of relocations
  1103  	for _, r := range ranges {
  1104  		ctxt.AddCURelativeAddress(sym, base, r.Start)
  1105  		ctxt.AddCURelativeAddress(sym, base, r.End)
  1106  	}
  1107  	// Write trailer.
  1108  	ctxt.AddInt(sym, ps, 0)
  1109  	ctxt.AddInt(sym, ps, 0)
  1110  }
  1111  
  1112  // Return TRUE if the inlined call in the specified slot is empty,
  1113  // meaning it has a zero-length range (no instructions), and all
  1114  // of its children are empty.
  1115  func isEmptyInlinedCall(slot int, calls *InlCalls) bool {
  1116  	ic := &calls.Calls[slot]
  1117  	if ic.InlIndex == -2 {
  1118  		return true
  1119  	}
  1120  	live := false
  1121  	for _, k := range ic.Children {
  1122  		if !isEmptyInlinedCall(k, calls) {
  1123  			live = true
  1124  		}
  1125  	}
  1126  	if len(ic.Ranges) > 0 {
  1127  		live = true
  1128  	}
  1129  	if !live {
  1130  		ic.InlIndex = -2
  1131  	}
  1132  	return !live
  1133  }
  1134  
  1135  // Slot -1:    return top-level inlines.
  1136  // Slot >= 0:  return children of that slot.
  1137  func inlChildren(slot int, calls *InlCalls) []int {
  1138  	var kids []int
  1139  	if slot != -1 {
  1140  		for _, k := range calls.Calls[slot].Children {
  1141  			if !isEmptyInlinedCall(k, calls) {
  1142  				kids = append(kids, k)
  1143  			}
  1144  		}
  1145  	} else {
  1146  		for k := 0; k < len(calls.Calls); k += 1 {
  1147  			if calls.Calls[k].Root && !isEmptyInlinedCall(k, calls) {
  1148  				kids = append(kids, k)
  1149  			}
  1150  		}
  1151  	}
  1152  	return kids
  1153  }
  1154  
  1155  func inlinedVarTable(inlcalls *InlCalls) map[*Var]bool {
  1156  	vars := make(map[*Var]bool)
  1157  	for _, ic := range inlcalls.Calls {
  1158  		for _, v := range ic.InlVars {
  1159  			vars[v] = true
  1160  		}
  1161  	}
  1162  	return vars
  1163  }
  1164  
  1165  // The s.Scopes slice contains variables were originally part of the
  1166  // function being emitted, as well as variables that were imported
  1167  // from various callee functions during the inlining process. This
  1168  // function prunes out any variables from the latter category (since
  1169  // they will be emitted as part of DWARF inlined_subroutine DIEs) and
  1170  // then generates scopes for vars in the former category.
  1171  func putPrunedScopes(ctxt Context, s *FnState, fnabbrev int) error {
  1172  	if len(s.Scopes) == 0 {
  1173  		return nil
  1174  	}
  1175  	scopes := make([]Scope, len(s.Scopes), len(s.Scopes))
  1176  	pvars := inlinedVarTable(&s.InlCalls)
  1177  	for k, s := range s.Scopes {
  1178  		var pruned Scope = Scope{Parent: s.Parent, Ranges: s.Ranges}
  1179  		for i := 0; i < len(s.Vars); i++ {
  1180  			_, found := pvars[s.Vars[i]]
  1181  			if !found {
  1182  				pruned.Vars = append(pruned.Vars, s.Vars[i])
  1183  			}
  1184  		}
  1185  		slices.SortFunc(pruned.Vars, byChildIndexCmp)
  1186  		scopes[k] = pruned
  1187  	}
  1188  
  1189  	s.dictIndexToOffset = putparamtypes(ctxt, s, scopes, fnabbrev)
  1190  
  1191  	var encbuf [20]byte
  1192  	if putscope(ctxt, s, scopes, 0, fnabbrev, encbuf[:0]) < int32(len(scopes)) {
  1193  		return errors.New("multiple toplevel scopes")
  1194  	}
  1195  	return nil
  1196  }
  1197  
  1198  // Emit DWARF attributes and child DIEs for an 'abstract' subprogram.
  1199  // The abstract subprogram DIE for a function contains its
  1200  // location-independent attributes (name, type, etc). Other instances
  1201  // of the function (any inlined copy of it, or the single out-of-line
  1202  // 'concrete' instance) will contain a pointer back to this abstract
  1203  // DIE (as a space-saving measure, so that name/type etc doesn't have
  1204  // to be repeated for each inlined copy).
  1205  func PutAbstractFunc(ctxt Context, s *FnState) error {
  1206  	if logDwarf {
  1207  		ctxt.Logf("PutAbstractFunc(%v)\n", s.Absfn)
  1208  	}
  1209  
  1210  	abbrev := DW_ABRV_FUNCTION_ABSTRACT
  1211  	Uleb128put(ctxt, s.Absfn, int64(abbrev))
  1212  
  1213  	fullname := s.Name
  1214  	if strings.HasPrefix(s.Name, `"".`) {
  1215  		return fmt.Errorf("unqualified symbol name: %v", s.Name)
  1216  	}
  1217  	putattr(ctxt, s.Absfn, abbrev, DW_FORM_string, DW_CLS_STRING, int64(len(fullname)), fullname)
  1218  
  1219  	// DW_AT_inlined value
  1220  	putattr(ctxt, s.Absfn, abbrev, DW_FORM_data1, DW_CLS_CONSTANT, int64(DW_INL_inlined), nil)
  1221  
  1222  	// TODO(mdempsky): Shouldn't we write out StartPos.FileIndex() too?
  1223  	putattr(ctxt, s.Absfn, abbrev, DW_FORM_udata, DW_CLS_CONSTANT, int64(s.StartPos.RelLine()), nil)
  1224  
  1225  	var ev int64
  1226  	if s.External {
  1227  		ev = 1
  1228  	}
  1229  	putattr(ctxt, s.Absfn, abbrev, DW_FORM_flag, DW_CLS_FLAG, ev, 0)
  1230  
  1231  	// Child variables (may be empty)
  1232  	var flattened []*Var
  1233  
  1234  	// This slice will hold the offset in bytes for each child var DIE
  1235  	// with respect to the start of the parent subprogram DIE.
  1236  	var offsets []int32
  1237  
  1238  	// Scopes/vars
  1239  	if len(s.Scopes) > 0 {
  1240  		// For abstract subprogram DIEs we want to flatten out scope info:
  1241  		// lexical scope DIEs contain range and/or hi/lo PC attributes,
  1242  		// which we explicitly don't want for the abstract subprogram DIE.
  1243  		pvars := inlinedVarTable(&s.InlCalls)
  1244  		for _, scope := range s.Scopes {
  1245  			for i := 0; i < len(scope.Vars); i++ {
  1246  				_, found := pvars[scope.Vars[i]]
  1247  				if found || !scope.Vars[i].IsInAbstract {
  1248  					continue
  1249  				}
  1250  				flattened = append(flattened, scope.Vars[i])
  1251  			}
  1252  		}
  1253  		if len(flattened) > 0 {
  1254  			slices.SortFunc(flattened, byChildIndexCmp)
  1255  
  1256  			if logDwarf {
  1257  				ctxt.Logf("putAbstractScope(%v): vars:", s.Info)
  1258  				for i, v := range flattened {
  1259  					ctxt.Logf(" %d:%s", i, v.Name)
  1260  				}
  1261  				ctxt.Logf("\n")
  1262  			}
  1263  
  1264  			// This slice will hold the offset in bytes for each child
  1265  			// variable DIE with respect to the start of the parent
  1266  			// subprogram DIE.
  1267  			for _, v := range flattened {
  1268  				offsets = append(offsets, int32(ctxt.CurrentOffset(s.Absfn)))
  1269  				putAbstractVar(ctxt, s.Absfn, v)
  1270  			}
  1271  		}
  1272  	}
  1273  	ctxt.RecordChildDieOffsets(s.Absfn, flattened, offsets)
  1274  
  1275  	Uleb128put(ctxt, s.Absfn, 0)
  1276  	return nil
  1277  }
  1278  
  1279  // dwarfFileIndex returns the DWARF file index value for the file associated
  1280  // with pos.
  1281  func dwarfFileIndex(pos src.Pos) int64 {
  1282  	return int64(1 + pos.FileIndex())
  1283  }
  1284  
  1285  // Emit DWARF attributes and child DIEs for an inlined subroutine. The
  1286  // first attribute of an inlined subroutine DIE is a reference back to
  1287  // its corresponding 'abstract' DIE (containing location-independent
  1288  // attributes such as name, type, etc). Inlined subroutine DIEs can
  1289  // have other inlined subroutine DIEs as children.
  1290  func putInlinedFunc(ctxt Context, s *FnState, callIdx int) error {
  1291  	ic := s.InlCalls.Calls[callIdx]
  1292  	callee := ic.AbsFunSym
  1293  
  1294  	// For DWARF 5, we always use the ranges form of the abbrev, since
  1295  	// it is more compact than using explicit hi/lo PC attrs.  See
  1296  	// issue #72821 for more on why this makes sense.
  1297  	abbrev := DW_ABRV_INLINED_SUBROUTINE_RANGES
  1298  	if len(ic.Ranges) == 1 && !buildcfg.Experiment.Dwarf5 {
  1299  		abbrev = DW_ABRV_INLINED_SUBROUTINE
  1300  	}
  1301  	Uleb128put(ctxt, s.Info, int64(abbrev))
  1302  
  1303  	if logDwarf {
  1304  		ctxt.Logf("putInlinedFunc(callee=%v,abbrev=%d)\n", callee, abbrev)
  1305  	}
  1306  
  1307  	// Abstract origin.
  1308  	putattr(ctxt, s.Info, abbrev, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, callee)
  1309  
  1310  	if abbrev == DW_ABRV_INLINED_SUBROUTINE_RANGES {
  1311  		putattr(ctxt, s.Info, abbrev, DW_FORM_sec_offset, DW_CLS_PTR, ctxt.Size(s.Ranges), s.Ranges)
  1312  		s.PutRanges(ctxt, ic.Ranges)
  1313  	} else {
  1314  		st := ic.Ranges[0].Start
  1315  		en := ic.Ranges[0].End
  1316  		emitHiLoPc(ctxt, abbrev, s, st, en)
  1317  	}
  1318  
  1319  	// Emit call file, line attrs.
  1320  	putattr(ctxt, s.Info, abbrev, DW_FORM_data4, DW_CLS_CONSTANT, dwarfFileIndex(ic.CallPos), nil)
  1321  	form := int(expandPseudoForm(DW_FORM_udata_pseudo))
  1322  	putattr(ctxt, s.Info, abbrev, form, DW_CLS_CONSTANT, int64(ic.CallPos.RelLine()), nil)
  1323  
  1324  	// Variables associated with this inlined routine instance.
  1325  	vars := ic.InlVars
  1326  	slices.SortFunc(vars, byChildIndexCmp)
  1327  	inlIndex := ic.InlIndex
  1328  	var encbuf [20]byte
  1329  	for _, v := range vars {
  1330  		if !v.IsInAbstract {
  1331  			continue
  1332  		}
  1333  		putvar(ctxt, s, v, callee, abbrev, inlIndex, encbuf[:0])
  1334  	}
  1335  
  1336  	// Children of this inline.
  1337  	for _, sib := range inlChildren(callIdx, &s.InlCalls) {
  1338  		err := putInlinedFunc(ctxt, s, sib)
  1339  		if err != nil {
  1340  			return err
  1341  		}
  1342  	}
  1343  
  1344  	Uleb128put(ctxt, s.Info, 0)
  1345  	return nil
  1346  }
  1347  
  1348  func emitHiLoPc(ctxt Context, abbrev int, fns *FnState, st int64, en int64) {
  1349  	if buildcfg.Experiment.Dwarf5 {
  1350  		putattr(ctxt, fns.Info, abbrev, DW_FORM_addrx, DW_CLS_CONSTANT, st, fns.StartPC)
  1351  		putattr(ctxt, fns.Info, abbrev, DW_FORM_udata, DW_CLS_CONSTANT, en, 0)
  1352  	} else {
  1353  		putattr(ctxt, fns.Info, abbrev, DW_FORM_addr, DW_CLS_ADDRESS, st, fns.StartPC)
  1354  		putattr(ctxt, fns.Info, abbrev, DW_FORM_addr, DW_CLS_ADDRESS, en, fns.StartPC)
  1355  	}
  1356  }
  1357  
  1358  // Emit DWARF attributes and child DIEs for a 'concrete' subprogram,
  1359  // meaning the out-of-line copy of a function that was inlined at some
  1360  // point during the compilation of its containing package. The first
  1361  // attribute for a concrete DIE is a reference to the 'abstract' DIE
  1362  // for the function (which holds location-independent attributes such
  1363  // as name, type), then the remainder of the attributes are specific
  1364  // to this instance (location, frame base, etc).
  1365  func PutConcreteFunc(ctxt Context, s *FnState, isWrapper bool, fncount int) error {
  1366  	if logDwarf {
  1367  		ctxt.Logf("PutConcreteFunc(%v)\n", s.Info)
  1368  	}
  1369  	abbrev := DW_ABRV_FUNCTION_CONCRETE
  1370  	if isWrapper {
  1371  		abbrev = DW_ABRV_WRAPPER_CONCRETE
  1372  	}
  1373  	Uleb128put(ctxt, s.Info, int64(abbrev))
  1374  
  1375  	// Abstract origin.
  1376  	putattr(ctxt, s.Info, abbrev, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, s.Absfn)
  1377  
  1378  	// Start/end PC.
  1379  	emitHiLoPc(ctxt, abbrev, s, 0, s.Size)
  1380  
  1381  	// cfa / frame base
  1382  	putattr(ctxt, s.Info, abbrev, DW_FORM_block1, DW_CLS_BLOCK, 1, []byte{DW_OP_call_frame_cfa})
  1383  
  1384  	if isWrapper {
  1385  		putattr(ctxt, s.Info, abbrev, DW_FORM_flag, DW_CLS_FLAG, int64(1), 0)
  1386  	}
  1387  
  1388  	// Scopes
  1389  	if err := putPrunedScopes(ctxt, s, abbrev); err != nil {
  1390  		return err
  1391  	}
  1392  
  1393  	// Inlined subroutines.
  1394  	for _, sib := range inlChildren(-1, &s.InlCalls) {
  1395  		err := putInlinedFunc(ctxt, s, sib)
  1396  		if err != nil {
  1397  			return err
  1398  		}
  1399  	}
  1400  
  1401  	Uleb128put(ctxt, s.Info, 0)
  1402  	return nil
  1403  }
  1404  
  1405  // Emit DWARF attributes and child DIEs for a subprogram. Here
  1406  // 'default' implies that the function in question was not inlined
  1407  // when its containing package was compiled (hence there is no need to
  1408  // emit an abstract version for it to use as a base for inlined
  1409  // routine records).
  1410  func PutDefaultFunc(ctxt Context, s *FnState, isWrapper bool) error {
  1411  	if logDwarf {
  1412  		ctxt.Logf("PutDefaultFunc(%v)\n", s.Info)
  1413  	}
  1414  	abbrev := DW_ABRV_FUNCTION
  1415  	if isWrapper {
  1416  		abbrev = DW_ABRV_WRAPPER
  1417  	}
  1418  	Uleb128put(ctxt, s.Info, int64(abbrev))
  1419  
  1420  	name := s.Name
  1421  	if strings.HasPrefix(name, `"".`) {
  1422  		return fmt.Errorf("unqualified symbol name: %v", name)
  1423  	}
  1424  
  1425  	putattr(ctxt, s.Info, DW_ABRV_FUNCTION, DW_FORM_string, DW_CLS_STRING, int64(len(name)), name)
  1426  	emitHiLoPc(ctxt, abbrev, s, 0, s.Size)
  1427  	putattr(ctxt, s.Info, abbrev, DW_FORM_block1, DW_CLS_BLOCK, 1, []byte{DW_OP_call_frame_cfa})
  1428  	if isWrapper {
  1429  		putattr(ctxt, s.Info, abbrev, DW_FORM_flag, DW_CLS_FLAG, int64(1), 0)
  1430  	} else {
  1431  		putattr(ctxt, s.Info, abbrev, DW_FORM_data4, DW_CLS_CONSTANT, dwarfFileIndex(s.StartPos), nil)
  1432  		putattr(ctxt, s.Info, abbrev, DW_FORM_udata, DW_CLS_CONSTANT, int64(s.StartPos.RelLine()), nil)
  1433  
  1434  		var ev int64
  1435  		if s.External {
  1436  			ev = 1
  1437  		}
  1438  		putattr(ctxt, s.Info, abbrev, DW_FORM_flag, DW_CLS_FLAG, ev, 0)
  1439  	}
  1440  
  1441  	// Scopes
  1442  	if err := putPrunedScopes(ctxt, s, abbrev); err != nil {
  1443  		return err
  1444  	}
  1445  
  1446  	// Inlined subroutines.
  1447  	for _, sib := range inlChildren(-1, &s.InlCalls) {
  1448  		err := putInlinedFunc(ctxt, s, sib)
  1449  		if err != nil {
  1450  			return err
  1451  		}
  1452  	}
  1453  
  1454  	Uleb128put(ctxt, s.Info, 0)
  1455  	return nil
  1456  }
  1457  
  1458  // putparamtypes writes typedef DIEs for any parametric types that are used by this function.
  1459  func putparamtypes(ctxt Context, s *FnState, scopes []Scope, fnabbrev int) []int64 {
  1460  	if fnabbrev == DW_ABRV_FUNCTION_CONCRETE {
  1461  		return nil
  1462  	}
  1463  
  1464  	maxDictIndex := uint16(0)
  1465  
  1466  	for i := range scopes {
  1467  		for _, v := range scopes[i].Vars {
  1468  			if v.DictIndex > maxDictIndex {
  1469  				maxDictIndex = v.DictIndex
  1470  			}
  1471  		}
  1472  	}
  1473  
  1474  	if maxDictIndex == 0 {
  1475  		return nil
  1476  	}
  1477  
  1478  	dictIndexToOffset := make([]int64, maxDictIndex)
  1479  
  1480  	for i := range scopes {
  1481  		for _, v := range scopes[i].Vars {
  1482  			if v.DictIndex == 0 || dictIndexToOffset[v.DictIndex-1] != 0 {
  1483  				continue
  1484  			}
  1485  
  1486  			dictIndexToOffset[v.DictIndex-1] = ctxt.CurrentOffset(s.Info)
  1487  
  1488  			Uleb128put(ctxt, s.Info, int64(DW_ABRV_DICT_INDEX))
  1489  			n := fmt.Sprintf(".param%d", v.DictIndex-1)
  1490  			putattr(ctxt, s.Info, DW_ABRV_DICT_INDEX, DW_FORM_string, DW_CLS_STRING, int64(len(n)), n)
  1491  			putattr(ctxt, s.Info, DW_ABRV_DICT_INDEX, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, v.Type)
  1492  			putattr(ctxt, s.Info, DW_ABRV_DICT_INDEX, DW_FORM_udata, DW_CLS_CONSTANT, int64(v.DictIndex-1), nil)
  1493  		}
  1494  	}
  1495  
  1496  	return dictIndexToOffset
  1497  }
  1498  
  1499  func putscope(ctxt Context, s *FnState, scopes []Scope, curscope int32, fnabbrev int, encbuf []byte) int32 {
  1500  
  1501  	if logDwarf {
  1502  		ctxt.Logf("putscope(%v,%d): vars:", s.Info, curscope)
  1503  		for i, v := range scopes[curscope].Vars {
  1504  			ctxt.Logf(" %d:%d:%s", i, v.ChildIndex, v.Name)
  1505  		}
  1506  		ctxt.Logf("\n")
  1507  	}
  1508  
  1509  	for _, v := range scopes[curscope].Vars {
  1510  		putvar(ctxt, s, v, s.Absfn, fnabbrev, -1, encbuf)
  1511  	}
  1512  	this := curscope
  1513  	curscope++
  1514  	for curscope < int32(len(scopes)) {
  1515  		scope := scopes[curscope]
  1516  		if scope.Parent != this {
  1517  			return curscope
  1518  		}
  1519  
  1520  		if len(scopes[curscope].Vars) == 0 {
  1521  			curscope = putscope(ctxt, s, scopes, curscope, fnabbrev, encbuf)
  1522  			continue
  1523  		}
  1524  
  1525  		// For DWARF 5, we always use the ranges form of the abbrev, since
  1526  		// it is more compact than using explicit hi/lo PC attrs.  See
  1527  		// issue #72821 for more on why this makes sense.
  1528  		if len(scope.Ranges) == 1 && !buildcfg.Experiment.Dwarf5 {
  1529  			Uleb128put(ctxt, s.Info, DW_ABRV_LEXICAL_BLOCK_SIMPLE)
  1530  			putattr(ctxt, s.Info, DW_ABRV_LEXICAL_BLOCK_SIMPLE, DW_FORM_addr, DW_CLS_ADDRESS, scope.Ranges[0].Start, s.StartPC)
  1531  			putattr(ctxt, s.Info, DW_ABRV_LEXICAL_BLOCK_SIMPLE, DW_FORM_addr, DW_CLS_ADDRESS, scope.Ranges[0].End, s.StartPC)
  1532  		} else {
  1533  			Uleb128put(ctxt, s.Info, DW_ABRV_LEXICAL_BLOCK_RANGES)
  1534  			putattr(ctxt, s.Info, DW_ABRV_LEXICAL_BLOCK_RANGES, DW_FORM_sec_offset, DW_CLS_PTR, ctxt.Size(s.Ranges), s.Ranges)
  1535  
  1536  			s.PutRanges(ctxt, scope.Ranges)
  1537  		}
  1538  
  1539  		curscope = putscope(ctxt, s, scopes, curscope, fnabbrev, encbuf)
  1540  
  1541  		Uleb128put(ctxt, s.Info, 0)
  1542  	}
  1543  	return curscope
  1544  }
  1545  
  1546  func concreteVar(fnabbrev int, v *Var) bool {
  1547  	concrete := true
  1548  	switch fnabbrev {
  1549  	case DW_ABRV_FUNCTION, DW_ABRV_WRAPPER:
  1550  		concrete = false
  1551  	case DW_ABRV_FUNCTION_CONCRETE, DW_ABRV_WRAPPER_CONCRETE:
  1552  		// If we're emitting a concrete subprogram DIE and the variable
  1553  		// in question is not part of the corresponding abstract function DIE,
  1554  		// then use the default (non-concrete) abbrev for this param.
  1555  		if !v.IsInAbstract {
  1556  			concrete = false
  1557  		}
  1558  	case DW_ABRV_INLINED_SUBROUTINE, DW_ABRV_INLINED_SUBROUTINE_RANGES:
  1559  	default:
  1560  		panic("should never happen")
  1561  	}
  1562  	return concrete
  1563  }
  1564  
  1565  // Emit DWARF attributes for a variable belonging to an 'abstract' subprogram.
  1566  func putAbstractVar(ctxt Context, info Sym, v *Var) {
  1567  	// The contents of this functions are used to generate putAbstractVarAbbrev automatically, see TestPutVarAbbrevGenerator.
  1568  	abbrev := putAbstractVarAbbrev(v)
  1569  	Uleb128put(ctxt, info, int64(abbrev))
  1570  	putattr(ctxt, info, abbrev, DW_FORM_string, DW_CLS_STRING, int64(len(v.Name)), v.Name) // DW_AT_name
  1571  
  1572  	// Isreturn attribute if this is a param
  1573  	if v.Tag == DW_TAG_formal_parameter {
  1574  		var isReturn int64
  1575  		if v.IsReturnValue {
  1576  			isReturn = 1
  1577  		}
  1578  		putattr(ctxt, info, abbrev, DW_FORM_flag, DW_CLS_FLAG, isReturn, nil) // DW_AT_variable_parameter
  1579  	}
  1580  
  1581  	// Line
  1582  	if v.Tag == DW_TAG_variable {
  1583  		// See issue 23374 for more on why decl line is skipped for abs params.
  1584  		putattr(ctxt, info, abbrev, DW_FORM_udata, DW_CLS_CONSTANT, int64(v.DeclLine), nil) // DW_AT_decl_line
  1585  	}
  1586  
  1587  	// Type
  1588  	putattr(ctxt, info, abbrev, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, v.Type) // DW_AT_type
  1589  
  1590  	// Var has no children => no terminator
  1591  }
  1592  
  1593  func putvar(ctxt Context, s *FnState, v *Var, absfn Sym, fnabbrev, inlIndex int, encbuf []byte) {
  1594  	// The contents of this functions are used to generate putvarAbbrev automatically, see TestPutVarAbbrevGenerator.
  1595  	concrete := concreteVar(fnabbrev, v)
  1596  	hasParametricType := !concrete && (v.DictIndex > 0 && s.dictIndexToOffset != nil && s.dictIndexToOffset[v.DictIndex-1] != 0)
  1597  	withLoclist := v.WithLoclist && v.PutLocationList != nil
  1598  
  1599  	abbrev := putvarAbbrev(v, concrete, withLoclist)
  1600  	Uleb128put(ctxt, s.Info, int64(abbrev))
  1601  
  1602  	// Abstract origin for concrete / inlined case
  1603  	if concrete {
  1604  		// Here we are making a reference to a child DIE of an abstract
  1605  		// function subprogram DIE. The child DIE has no LSym, so instead
  1606  		// after the call to 'putattr' below we make a call to register
  1607  		// the child DIE reference.
  1608  		putattr(ctxt, s.Info, abbrev, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, absfn) // DW_AT_abstract_origin
  1609  		ctxt.RecordDclReference(s.Info, absfn, int(v.ChildIndex), inlIndex)
  1610  	} else {
  1611  		// Var name, line for abstract and default cases
  1612  		n := v.Name
  1613  		putattr(ctxt, s.Info, abbrev, DW_FORM_string, DW_CLS_STRING, int64(len(n)), n) // DW_AT_name
  1614  		if v.Tag == DW_TAG_formal_parameter {
  1615  			var isReturn int64
  1616  			if v.IsReturnValue {
  1617  				isReturn = 1
  1618  			}
  1619  			putattr(ctxt, s.Info, abbrev, DW_FORM_flag, DW_CLS_FLAG, isReturn, nil) // DW_AT_variable_parameter
  1620  		}
  1621  		putattr(ctxt, s.Info, abbrev, DW_FORM_udata, DW_CLS_CONSTANT, int64(v.DeclLine), nil) // DW_AT_decl_line
  1622  		if hasParametricType {
  1623  			// If the type of this variable is parametric use the entry emitted by putparamtypes
  1624  			putattr(ctxt, s.Info, abbrev, DW_FORM_ref_addr, DW_CLS_REFERENCE, s.dictIndexToOffset[v.DictIndex-1], s.Info) // DW_AT_type
  1625  		} else {
  1626  			putattr(ctxt, s.Info, abbrev, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, v.Type) // DW_AT_type
  1627  		}
  1628  
  1629  		if v.ClosureOffset > 0 {
  1630  			putattr(ctxt, s.Info, abbrev, DW_FORM_udata, DW_CLS_CONSTANT, v.ClosureOffset, nil) // DW_AT_go_closure_offset
  1631  		}
  1632  	}
  1633  
  1634  	if withLoclist {
  1635  		putattr(ctxt, s.Info, abbrev, DW_FORM_sec_offset, DW_CLS_PTR, ctxt.Size(s.Loc), s.Loc) // DW_AT_location
  1636  		v.PutLocationList(s.Loc, s.StartPC)
  1637  	} else {
  1638  		loc := encbuf[:0]
  1639  		switch {
  1640  		case v.WithLoclist:
  1641  			break // no location
  1642  		case v.StackOffset == 0:
  1643  			loc = append(loc, DW_OP_call_frame_cfa)
  1644  		default:
  1645  			loc = append(loc, DW_OP_fbreg)
  1646  			loc = AppendSleb128(loc, int64(v.StackOffset))
  1647  		}
  1648  		putattr(ctxt, s.Info, abbrev, DW_FORM_block1, DW_CLS_BLOCK, int64(len(loc)), loc) // DW_AT_location
  1649  	}
  1650  
  1651  	// Var has no children => no terminator
  1652  }
  1653  
  1654  // byChildIndexCmp compares two *dwarf.Var by child index.
  1655  func byChildIndexCmp(a, b *Var) int { return cmp.Compare(a.ChildIndex, b.ChildIndex) }
  1656  
  1657  // IsDWARFEnabledOnAIXLd returns true if DWARF is possible on the
  1658  // current extld.
  1659  // AIX ld doesn't support DWARF with -bnoobjreorder with version
  1660  // prior to 7.2.2.
  1661  func IsDWARFEnabledOnAIXLd(extld []string) (bool, error) {
  1662  	name, args := extld[0], extld[1:]
  1663  	args = append(args, "-Wl,-V")
  1664  	out, err := exec.Command(name, args...).CombinedOutput()
  1665  	if err != nil {
  1666  		// The normal output should display ld version and
  1667  		// then fails because ".main" is not defined:
  1668  		// ld: 0711-317 ERROR: Undefined symbol: .main
  1669  		if !bytes.Contains(out, []byte("0711-317")) {
  1670  			return false, fmt.Errorf("%s -Wl,-V failed: %v\n%s", extld, err, out)
  1671  		}
  1672  	}
  1673  	// gcc -Wl,-V output should be:
  1674  	//   /usr/bin/ld: LD X.X.X(date)
  1675  	//   ...
  1676  	out = bytes.TrimPrefix(out, []byte("/usr/bin/ld: LD "))
  1677  	vers := string(bytes.Split(out, []byte("("))[0])
  1678  	subvers := strings.Split(vers, ".")
  1679  	if len(subvers) != 3 {
  1680  		return false, fmt.Errorf("cannot parse %s -Wl,-V (%s): %v\n", extld, out, err)
  1681  	}
  1682  	if v, err := strconv.Atoi(subvers[0]); err != nil || v < 7 {
  1683  		return false, nil
  1684  	} else if v > 7 {
  1685  		return true, nil
  1686  	}
  1687  	if v, err := strconv.Atoi(subvers[1]); err != nil || v < 2 {
  1688  		return false, nil
  1689  	} else if v > 2 {
  1690  		return true, nil
  1691  	}
  1692  	if v, err := strconv.Atoi(subvers[2]); err != nil || v < 2 {
  1693  		return false, nil
  1694  	}
  1695  	return true, nil
  1696  }
  1697  

View as plain text