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

View as plain text