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

View as plain text