...
Run Format

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

Documentation: cmd/internal/dwarf

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

View as plain text