github.com/goproxy0/go@v0.0.0-20171111080102-49cc0c489d2c/src/cmd/internal/dwarf/dwarf.go (about)

     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  	"errors"
    12  	"fmt"
    13  )
    14  
    15  // InfoPrefix is the prefix for all the symbols containing DWARF info entries.
    16  const InfoPrefix = "go.info."
    17  
    18  // RangePrefix is the prefix for all the symbols containing DWARF location lists.
    19  const LocPrefix = "go.loc."
    20  
    21  // RangePrefix is the prefix for all the symbols containing DWARF range lists.
    22  const RangePrefix = "go.range."
    23  
    24  // ConstInfoPrefix is the prefix for all symbols containing DWARF info
    25  // entries that contain constants.
    26  const ConstInfoPrefix = "go.constinfo."
    27  
    28  // CUInfoPrefix is the prefix for symbols containing information to
    29  // populate the DWARF compilation unit info entries.
    30  const CUInfoPrefix = "go.cuinfo."
    31  
    32  // Sym represents a symbol.
    33  type Sym interface {
    34  	Len() int64
    35  }
    36  
    37  // A Location represents a variable's location at a particular PC range.
    38  // It becomes a location list entry in the DWARF.
    39  type Location struct {
    40  	StartPC, EndPC int64
    41  	Pieces         []Piece
    42  }
    43  
    44  // A Piece represents the location of a particular part of a variable.
    45  // It becomes part of a location list entry (a DW_OP_piece) in the DWARF.
    46  type Piece struct {
    47  	Length      int64
    48  	StackOffset int32
    49  	RegNum      int16
    50  	Missing     bool
    51  	OnStack     bool // if true, RegNum is unset.
    52  }
    53  
    54  // A Var represents a local variable or a function parameter.
    55  type Var struct {
    56  	Name          string
    57  	Abbrev        int // Either DW_ABRV_AUTO[_LOCLIST] or DW_ABRV_PARAM[_LOCLIST]
    58  	IsReturnValue bool
    59  	StackOffset   int32
    60  	LocationList  []Location
    61  	Scope         int32
    62  	Type          Sym
    63  	DeclLine      uint
    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  // UnifyRanges merges the list of ranges of c into the list of ranges of s
    84  func (s *Scope) UnifyRanges(c *Scope) {
    85  	out := make([]Range, 0, len(s.Ranges)+len(c.Ranges))
    86  
    87  	i, j := 0, 0
    88  	for {
    89  		var cur Range
    90  		if i < len(s.Ranges) && j < len(c.Ranges) {
    91  			if s.Ranges[i].Start < c.Ranges[j].Start {
    92  				cur = s.Ranges[i]
    93  				i++
    94  			} else {
    95  				cur = c.Ranges[j]
    96  				j++
    97  			}
    98  		} else if i < len(s.Ranges) {
    99  			cur = s.Ranges[i]
   100  			i++
   101  		} else if j < len(c.Ranges) {
   102  			cur = c.Ranges[j]
   103  			j++
   104  		} else {
   105  			break
   106  		}
   107  
   108  		if n := len(out); n > 0 && cur.Start <= out[n-1].End {
   109  			out[n-1].End = cur.End
   110  		} else {
   111  			out = append(out, cur)
   112  		}
   113  	}
   114  
   115  	s.Ranges = out
   116  }
   117  
   118  // A Context specifies how to add data to a Sym.
   119  type Context interface {
   120  	PtrSize() int
   121  	AddInt(s Sym, size int, i int64)
   122  	AddBytes(s Sym, b []byte)
   123  	AddAddress(s Sym, t interface{}, ofs int64)
   124  	AddCURelativeAddress(s Sym, t interface{}, ofs int64)
   125  	AddSectionOffset(s Sym, size int, t interface{}, ofs int64)
   126  	AddString(s Sym, v string)
   127  	AddFileRef(s Sym, f interface{})
   128  }
   129  
   130  // AppendUleb128 appends v to b using DWARF's unsigned LEB128 encoding.
   131  func AppendUleb128(b []byte, v uint64) []byte {
   132  	for {
   133  		c := uint8(v & 0x7f)
   134  		v >>= 7
   135  		if v != 0 {
   136  			c |= 0x80
   137  		}
   138  		b = append(b, c)
   139  		if c&0x80 == 0 {
   140  			break
   141  		}
   142  	}
   143  	return b
   144  }
   145  
   146  // AppendSleb128 appends v to b using DWARF's signed LEB128 encoding.
   147  func AppendSleb128(b []byte, v int64) []byte {
   148  	for {
   149  		c := uint8(v & 0x7f)
   150  		s := uint8(v & 0x40)
   151  		v >>= 7
   152  		if (v != -1 || s == 0) && (v != 0 || s != 0) {
   153  			c |= 0x80
   154  		}
   155  		b = append(b, c)
   156  		if c&0x80 == 0 {
   157  			break
   158  		}
   159  	}
   160  	return b
   161  }
   162  
   163  // sevenbits contains all unsigned seven bit numbers, indexed by their value.
   164  var sevenbits = [...]byte{
   165  	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
   166  	0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
   167  	0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
   168  	0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
   169  	0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
   170  	0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
   171  	0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
   172  	0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
   173  }
   174  
   175  // sevenBitU returns the unsigned LEB128 encoding of v if v is seven bits and nil otherwise.
   176  // The contents of the returned slice must not be modified.
   177  func sevenBitU(v int64) []byte {
   178  	if uint64(v) < uint64(len(sevenbits)) {
   179  		return sevenbits[v : v+1]
   180  	}
   181  	return nil
   182  }
   183  
   184  // sevenBitS returns the signed LEB128 encoding of v if v is seven bits and nil otherwise.
   185  // The contents of the returned slice must not be modified.
   186  func sevenBitS(v int64) []byte {
   187  	if uint64(v) <= 63 {
   188  		return sevenbits[v : v+1]
   189  	}
   190  	if uint64(-v) <= 64 {
   191  		return sevenbits[128+v : 128+v+1]
   192  	}
   193  	return nil
   194  }
   195  
   196  // Uleb128put appends v to s using DWARF's unsigned LEB128 encoding.
   197  func Uleb128put(ctxt Context, s Sym, v int64) {
   198  	b := sevenBitU(v)
   199  	if b == nil {
   200  		var encbuf [20]byte
   201  		b = AppendUleb128(encbuf[:0], uint64(v))
   202  	}
   203  	ctxt.AddBytes(s, b)
   204  }
   205  
   206  // Sleb128put appends v to s using DWARF's signed LEB128 encoding.
   207  func Sleb128put(ctxt Context, s Sym, v int64) {
   208  	b := sevenBitS(v)
   209  	if b == nil {
   210  		var encbuf [20]byte
   211  		b = AppendSleb128(encbuf[:0], v)
   212  	}
   213  	ctxt.AddBytes(s, b)
   214  }
   215  
   216  /*
   217   * Defining Abbrevs.  This is hardcoded, and there will be
   218   * only a handful of them.  The DWARF spec places no restriction on
   219   * the ordering of attributes in the Abbrevs and DIEs, and we will
   220   * always write them out in the order of declaration in the abbrev.
   221   */
   222  type dwAttrForm struct {
   223  	attr uint16
   224  	form uint8
   225  }
   226  
   227  // Go-specific type attributes.
   228  const (
   229  	DW_AT_go_kind = 0x2900
   230  	DW_AT_go_key  = 0x2901
   231  	DW_AT_go_elem = 0x2902
   232  	// Attribute for DW_TAG_member of a struct type.
   233  	// Nonzero value indicates the struct field is an embedded field.
   234  	DW_AT_go_embedded_field = 0x2903
   235  
   236  	DW_AT_internal_location = 253 // params and locals; not emitted
   237  )
   238  
   239  // Index into the abbrevs table below.
   240  // Keep in sync with ispubname() and ispubtype() in ld/dwarf.go.
   241  // ispubtype considers >= NULLTYPE public
   242  const (
   243  	DW_ABRV_NULL = iota
   244  	DW_ABRV_COMPUNIT
   245  	DW_ABRV_FUNCTION
   246  	DW_ABRV_VARIABLE
   247  	DW_ABRV_INT_CONSTANT
   248  	DW_ABRV_AUTO
   249  	DW_ABRV_AUTO_LOCLIST
   250  	DW_ABRV_PARAM
   251  	DW_ABRV_PARAM_LOCLIST
   252  	DW_ABRV_LEXICAL_BLOCK_RANGES
   253  	DW_ABRV_LEXICAL_BLOCK_SIMPLE
   254  	DW_ABRV_STRUCTFIELD
   255  	DW_ABRV_FUNCTYPEPARAM
   256  	DW_ABRV_DOTDOTDOT
   257  	DW_ABRV_ARRAYRANGE
   258  	DW_ABRV_NULLTYPE
   259  	DW_ABRV_BASETYPE
   260  	DW_ABRV_ARRAYTYPE
   261  	DW_ABRV_CHANTYPE
   262  	DW_ABRV_FUNCTYPE
   263  	DW_ABRV_IFACETYPE
   264  	DW_ABRV_MAPTYPE
   265  	DW_ABRV_PTRTYPE
   266  	DW_ABRV_BARE_PTRTYPE // only for void*, no DW_AT_type attr to please gdb 6.
   267  	DW_ABRV_SLICETYPE
   268  	DW_ABRV_STRINGTYPE
   269  	DW_ABRV_STRUCTTYPE
   270  	DW_ABRV_TYPEDECL
   271  	DW_NABRV
   272  )
   273  
   274  type dwAbbrev struct {
   275  	tag      uint8
   276  	children uint8
   277  	attr     []dwAttrForm
   278  }
   279  
   280  var abbrevs = [DW_NABRV]dwAbbrev{
   281  	/* The mandatory DW_ABRV_NULL entry. */
   282  	{0, 0, []dwAttrForm{}},
   283  
   284  	/* COMPUNIT */
   285  	{
   286  		DW_TAG_compile_unit,
   287  		DW_CHILDREN_yes,
   288  		[]dwAttrForm{
   289  			{DW_AT_name, DW_FORM_string},
   290  			{DW_AT_language, DW_FORM_data1},
   291  			{DW_AT_stmt_list, DW_FORM_sec_offset},
   292  			{DW_AT_low_pc, DW_FORM_addr},
   293  			{DW_AT_ranges, DW_FORM_sec_offset},
   294  			{DW_AT_comp_dir, DW_FORM_string},
   295  			{DW_AT_producer, DW_FORM_string},
   296  		},
   297  	},
   298  
   299  	/* FUNCTION */
   300  	{
   301  		DW_TAG_subprogram,
   302  		DW_CHILDREN_yes,
   303  		[]dwAttrForm{
   304  			{DW_AT_name, DW_FORM_string},
   305  			{DW_AT_low_pc, DW_FORM_addr},
   306  			{DW_AT_high_pc, DW_FORM_addr},
   307  			{DW_AT_frame_base, DW_FORM_block1},
   308  			{DW_AT_decl_file, DW_FORM_data4},
   309  			{DW_AT_external, DW_FORM_flag},
   310  		},
   311  	},
   312  
   313  	/* VARIABLE */
   314  	{
   315  		DW_TAG_variable,
   316  		DW_CHILDREN_no,
   317  		[]dwAttrForm{
   318  			{DW_AT_name, DW_FORM_string},
   319  			{DW_AT_location, DW_FORM_block1},
   320  			{DW_AT_type, DW_FORM_ref_addr},
   321  			{DW_AT_external, DW_FORM_flag},
   322  		},
   323  	},
   324  
   325  	/* INT CONSTANT */
   326  	{
   327  		DW_TAG_constant,
   328  		DW_CHILDREN_no,
   329  		[]dwAttrForm{
   330  			{DW_AT_name, DW_FORM_string},
   331  			{DW_AT_type, DW_FORM_ref_addr},
   332  			{DW_AT_const_value, DW_FORM_sdata},
   333  		},
   334  	},
   335  
   336  	/* AUTO */
   337  	{
   338  		DW_TAG_variable,
   339  		DW_CHILDREN_no,
   340  		[]dwAttrForm{
   341  			{DW_AT_name, DW_FORM_string},
   342  			{DW_AT_decl_line, DW_FORM_udata},
   343  			{DW_AT_location, DW_FORM_block1},
   344  			{DW_AT_type, DW_FORM_ref_addr},
   345  		},
   346  	},
   347  
   348  	/* AUTO_LOCLIST */
   349  	{
   350  		DW_TAG_variable,
   351  		DW_CHILDREN_no,
   352  		[]dwAttrForm{
   353  			{DW_AT_name, DW_FORM_string},
   354  			{DW_AT_decl_line, DW_FORM_udata},
   355  			{DW_AT_location, DW_FORM_sec_offset},
   356  			{DW_AT_type, DW_FORM_ref_addr},
   357  		},
   358  	},
   359  
   360  	/* PARAM */
   361  	{
   362  		DW_TAG_formal_parameter,
   363  		DW_CHILDREN_no,
   364  		[]dwAttrForm{
   365  			{DW_AT_name, DW_FORM_string},
   366  			{DW_AT_variable_parameter, DW_FORM_flag},
   367  			{DW_AT_decl_line, DW_FORM_udata},
   368  			{DW_AT_location, DW_FORM_block1},
   369  			{DW_AT_type, DW_FORM_ref_addr},
   370  		},
   371  	},
   372  
   373  	/* PARAM_LOCLIST */
   374  	{
   375  		DW_TAG_formal_parameter,
   376  		DW_CHILDREN_no,
   377  		[]dwAttrForm{
   378  			{DW_AT_name, DW_FORM_string},
   379  			{DW_AT_variable_parameter, DW_FORM_flag},
   380  			{DW_AT_decl_line, DW_FORM_udata},
   381  			{DW_AT_location, DW_FORM_sec_offset},
   382  			{DW_AT_type, DW_FORM_ref_addr},
   383  		},
   384  	},
   385  
   386  	/* LEXICAL_BLOCK_RANGES */
   387  	{
   388  		DW_TAG_lexical_block,
   389  		DW_CHILDREN_yes,
   390  		[]dwAttrForm{
   391  			{DW_AT_ranges, DW_FORM_sec_offset},
   392  		},
   393  	},
   394  
   395  	/* LEXICAL_BLOCK_SIMPLE */
   396  	{
   397  		DW_TAG_lexical_block,
   398  		DW_CHILDREN_yes,
   399  		[]dwAttrForm{
   400  			{DW_AT_low_pc, DW_FORM_addr},
   401  			{DW_AT_high_pc, DW_FORM_addr},
   402  		},
   403  	},
   404  
   405  	/* STRUCTFIELD */
   406  	{
   407  		DW_TAG_member,
   408  		DW_CHILDREN_no,
   409  		[]dwAttrForm{
   410  			{DW_AT_name, DW_FORM_string},
   411  			{DW_AT_data_member_location, DW_FORM_udata},
   412  			{DW_AT_type, DW_FORM_ref_addr},
   413  			{DW_AT_go_embedded_field, DW_FORM_flag},
   414  		},
   415  	},
   416  
   417  	/* FUNCTYPEPARAM */
   418  	{
   419  		DW_TAG_formal_parameter,
   420  		DW_CHILDREN_no,
   421  
   422  		// No name!
   423  		[]dwAttrForm{
   424  			{DW_AT_type, DW_FORM_ref_addr},
   425  		},
   426  	},
   427  
   428  	/* DOTDOTDOT */
   429  	{
   430  		DW_TAG_unspecified_parameters,
   431  		DW_CHILDREN_no,
   432  		[]dwAttrForm{},
   433  	},
   434  
   435  	/* ARRAYRANGE */
   436  	{
   437  		DW_TAG_subrange_type,
   438  		DW_CHILDREN_no,
   439  
   440  		// No name!
   441  		[]dwAttrForm{
   442  			{DW_AT_type, DW_FORM_ref_addr},
   443  			{DW_AT_count, DW_FORM_udata},
   444  		},
   445  	},
   446  
   447  	// Below here are the types considered public by ispubtype
   448  	/* NULLTYPE */
   449  	{
   450  		DW_TAG_unspecified_type,
   451  		DW_CHILDREN_no,
   452  		[]dwAttrForm{
   453  			{DW_AT_name, DW_FORM_string},
   454  		},
   455  	},
   456  
   457  	/* BASETYPE */
   458  	{
   459  		DW_TAG_base_type,
   460  		DW_CHILDREN_no,
   461  		[]dwAttrForm{
   462  			{DW_AT_name, DW_FORM_string},
   463  			{DW_AT_encoding, DW_FORM_data1},
   464  			{DW_AT_byte_size, DW_FORM_data1},
   465  			{DW_AT_go_kind, DW_FORM_data1},
   466  		},
   467  	},
   468  
   469  	/* ARRAYTYPE */
   470  	// child is subrange with upper bound
   471  	{
   472  		DW_TAG_array_type,
   473  		DW_CHILDREN_yes,
   474  		[]dwAttrForm{
   475  			{DW_AT_name, DW_FORM_string},
   476  			{DW_AT_type, DW_FORM_ref_addr},
   477  			{DW_AT_byte_size, DW_FORM_udata},
   478  			{DW_AT_go_kind, DW_FORM_data1},
   479  		},
   480  	},
   481  
   482  	/* CHANTYPE */
   483  	{
   484  		DW_TAG_typedef,
   485  		DW_CHILDREN_no,
   486  		[]dwAttrForm{
   487  			{DW_AT_name, DW_FORM_string},
   488  			{DW_AT_type, DW_FORM_ref_addr},
   489  			{DW_AT_go_kind, DW_FORM_data1},
   490  			{DW_AT_go_elem, DW_FORM_ref_addr},
   491  		},
   492  	},
   493  
   494  	/* FUNCTYPE */
   495  	{
   496  		DW_TAG_subroutine_type,
   497  		DW_CHILDREN_yes,
   498  		[]dwAttrForm{
   499  			{DW_AT_name, DW_FORM_string},
   500  			{DW_AT_byte_size, DW_FORM_udata},
   501  			// {DW_AT_type,	DW_FORM_ref_addr},
   502  			{DW_AT_go_kind, DW_FORM_data1},
   503  		},
   504  	},
   505  
   506  	/* IFACETYPE */
   507  	{
   508  		DW_TAG_typedef,
   509  		DW_CHILDREN_yes,
   510  		[]dwAttrForm{
   511  			{DW_AT_name, DW_FORM_string},
   512  			{DW_AT_type, DW_FORM_ref_addr},
   513  			{DW_AT_go_kind, DW_FORM_data1},
   514  		},
   515  	},
   516  
   517  	/* MAPTYPE */
   518  	{
   519  		DW_TAG_typedef,
   520  		DW_CHILDREN_no,
   521  		[]dwAttrForm{
   522  			{DW_AT_name, DW_FORM_string},
   523  			{DW_AT_type, DW_FORM_ref_addr},
   524  			{DW_AT_go_kind, DW_FORM_data1},
   525  			{DW_AT_go_key, DW_FORM_ref_addr},
   526  			{DW_AT_go_elem, DW_FORM_ref_addr},
   527  		},
   528  	},
   529  
   530  	/* PTRTYPE */
   531  	{
   532  		DW_TAG_pointer_type,
   533  		DW_CHILDREN_no,
   534  		[]dwAttrForm{
   535  			{DW_AT_name, DW_FORM_string},
   536  			{DW_AT_type, DW_FORM_ref_addr},
   537  			{DW_AT_go_kind, DW_FORM_data1},
   538  		},
   539  	},
   540  
   541  	/* BARE_PTRTYPE */
   542  	{
   543  		DW_TAG_pointer_type,
   544  		DW_CHILDREN_no,
   545  		[]dwAttrForm{
   546  			{DW_AT_name, DW_FORM_string},
   547  		},
   548  	},
   549  
   550  	/* SLICETYPE */
   551  	{
   552  		DW_TAG_structure_type,
   553  		DW_CHILDREN_yes,
   554  		[]dwAttrForm{
   555  			{DW_AT_name, DW_FORM_string},
   556  			{DW_AT_byte_size, DW_FORM_udata},
   557  			{DW_AT_go_kind, DW_FORM_data1},
   558  			{DW_AT_go_elem, DW_FORM_ref_addr},
   559  		},
   560  	},
   561  
   562  	/* STRINGTYPE */
   563  	{
   564  		DW_TAG_structure_type,
   565  		DW_CHILDREN_yes,
   566  		[]dwAttrForm{
   567  			{DW_AT_name, DW_FORM_string},
   568  			{DW_AT_byte_size, DW_FORM_udata},
   569  			{DW_AT_go_kind, DW_FORM_data1},
   570  		},
   571  	},
   572  
   573  	/* STRUCTTYPE */
   574  	{
   575  		DW_TAG_structure_type,
   576  		DW_CHILDREN_yes,
   577  		[]dwAttrForm{
   578  			{DW_AT_name, DW_FORM_string},
   579  			{DW_AT_byte_size, DW_FORM_udata},
   580  			{DW_AT_go_kind, DW_FORM_data1},
   581  		},
   582  	},
   583  
   584  	/* TYPEDECL */
   585  	{
   586  		DW_TAG_typedef,
   587  		DW_CHILDREN_no,
   588  		[]dwAttrForm{
   589  			{DW_AT_name, DW_FORM_string},
   590  			{DW_AT_type, DW_FORM_ref_addr},
   591  		},
   592  	},
   593  }
   594  
   595  // GetAbbrev returns the contents of the .debug_abbrev section.
   596  func GetAbbrev() []byte {
   597  	var buf []byte
   598  	for i := 1; i < DW_NABRV; i++ {
   599  		// See section 7.5.3
   600  		buf = AppendUleb128(buf, uint64(i))
   601  		buf = AppendUleb128(buf, uint64(abbrevs[i].tag))
   602  		buf = append(buf, byte(abbrevs[i].children))
   603  		for _, f := range abbrevs[i].attr {
   604  			buf = AppendUleb128(buf, uint64(f.attr))
   605  			buf = AppendUleb128(buf, uint64(f.form))
   606  		}
   607  		buf = append(buf, 0, 0)
   608  	}
   609  	return append(buf, 0)
   610  }
   611  
   612  /*
   613   * Debugging Information Entries and their attributes.
   614   */
   615  
   616  // DWAttr represents an attribute of a DWDie.
   617  //
   618  // For DW_CLS_string and _block, value should contain the length, and
   619  // data the data, for _reference, value is 0 and data is a DWDie* to
   620  // the referenced instance, for all others, value is the whole thing
   621  // and data is null.
   622  type DWAttr struct {
   623  	Link  *DWAttr
   624  	Atr   uint16 // DW_AT_
   625  	Cls   uint8  // DW_CLS_
   626  	Value int64
   627  	Data  interface{}
   628  }
   629  
   630  // DWDie represents a DWARF debug info entry.
   631  type DWDie struct {
   632  	Abbrev int
   633  	Link   *DWDie
   634  	Child  *DWDie
   635  	Attr   *DWAttr
   636  	Sym    Sym
   637  }
   638  
   639  func putattr(ctxt Context, s Sym, abbrev int, form int, cls int, value int64, data interface{}) error {
   640  	switch form {
   641  	case DW_FORM_addr: // address
   642  		ctxt.AddAddress(s, data, value)
   643  
   644  	case DW_FORM_block1: // block
   645  		if cls == DW_CLS_ADDRESS {
   646  			ctxt.AddInt(s, 1, int64(1+ctxt.PtrSize()))
   647  			ctxt.AddInt(s, 1, DW_OP_addr)
   648  			ctxt.AddAddress(s, data, 0)
   649  			break
   650  		}
   651  
   652  		value &= 0xff
   653  		ctxt.AddInt(s, 1, value)
   654  		p := data.([]byte)[:value]
   655  		ctxt.AddBytes(s, p)
   656  
   657  	case DW_FORM_block2: // block
   658  		value &= 0xffff
   659  
   660  		ctxt.AddInt(s, 2, value)
   661  		p := data.([]byte)[:value]
   662  		ctxt.AddBytes(s, p)
   663  
   664  	case DW_FORM_block4: // block
   665  		value &= 0xffffffff
   666  
   667  		ctxt.AddInt(s, 4, value)
   668  		p := data.([]byte)[:value]
   669  		ctxt.AddBytes(s, p)
   670  
   671  	case DW_FORM_block: // block
   672  		Uleb128put(ctxt, s, value)
   673  
   674  		p := data.([]byte)[:value]
   675  		ctxt.AddBytes(s, p)
   676  
   677  	case DW_FORM_data1: // constant
   678  		ctxt.AddInt(s, 1, value)
   679  
   680  	case DW_FORM_data2: // constant
   681  		ctxt.AddInt(s, 2, value)
   682  
   683  	case DW_FORM_data4: // constant, {line,loclist,mac,rangelist}ptr
   684  		if cls == DW_CLS_PTR { // DW_AT_stmt_list and DW_AT_ranges
   685  			ctxt.AddSectionOffset(s, 4, data, value)
   686  			break
   687  		}
   688  		ctxt.AddInt(s, 4, value)
   689  
   690  	case DW_FORM_data8: // constant, {line,loclist,mac,rangelist}ptr
   691  		ctxt.AddInt(s, 8, value)
   692  
   693  	case DW_FORM_sdata: // constant
   694  		Sleb128put(ctxt, s, value)
   695  
   696  	case DW_FORM_udata: // constant
   697  		Uleb128put(ctxt, s, value)
   698  
   699  	case DW_FORM_string: // string
   700  		str := data.(string)
   701  		ctxt.AddString(s, str)
   702  		// TODO(ribrdb): verify padded strings are never used and remove this
   703  		for i := int64(len(str)); i < value; i++ {
   704  			ctxt.AddInt(s, 1, 0)
   705  		}
   706  
   707  	case DW_FORM_flag: // flag
   708  		if value != 0 {
   709  			ctxt.AddInt(s, 1, 1)
   710  		} else {
   711  			ctxt.AddInt(s, 1, 0)
   712  		}
   713  
   714  	// As of DWARF 3 the ref_addr is always 32 bits, unless emitting a large
   715  	// (> 4 GB of debug info aka "64-bit") unit, which we don't implement.
   716  	case DW_FORM_ref_addr: // reference to a DIE in the .info section
   717  		fallthrough
   718  	case DW_FORM_sec_offset: // offset into a DWARF section other than .info
   719  		if data == nil {
   720  			return fmt.Errorf("dwarf: null reference in %d", abbrev)
   721  		}
   722  		ctxt.AddSectionOffset(s, 4, data, value)
   723  
   724  	case DW_FORM_ref1, // reference within the compilation unit
   725  		DW_FORM_ref2,      // reference
   726  		DW_FORM_ref4,      // reference
   727  		DW_FORM_ref8,      // reference
   728  		DW_FORM_ref_udata, // reference
   729  
   730  		DW_FORM_strp,     // string
   731  		DW_FORM_indirect: // (see Section 7.5.3)
   732  		fallthrough
   733  	default:
   734  		return fmt.Errorf("dwarf: unsupported attribute form %d / class %d", form, cls)
   735  	}
   736  	return nil
   737  }
   738  
   739  // PutAttrs writes the attributes for a DIE to symbol 's'.
   740  //
   741  // Note that we can (and do) add arbitrary attributes to a DIE, but
   742  // only the ones actually listed in the Abbrev will be written out.
   743  func PutAttrs(ctxt Context, s Sym, abbrev int, attr *DWAttr) {
   744  Outer:
   745  	for _, f := range abbrevs[abbrev].attr {
   746  		for ap := attr; ap != nil; ap = ap.Link {
   747  			if ap.Atr == f.attr {
   748  				putattr(ctxt, s, abbrev, int(f.form), int(ap.Cls), ap.Value, ap.Data)
   749  				continue Outer
   750  			}
   751  		}
   752  
   753  		putattr(ctxt, s, abbrev, int(f.form), 0, 0, nil)
   754  	}
   755  }
   756  
   757  // HasChildren returns true if 'die' uses an abbrev that supports children.
   758  func HasChildren(die *DWDie) bool {
   759  	return abbrevs[die.Abbrev].children != 0
   760  }
   761  
   762  // PutIntConst writes a DIE for an integer constant
   763  func PutIntConst(ctxt Context, info, typ Sym, name string, val int64) {
   764  	Uleb128put(ctxt, info, DW_ABRV_INT_CONSTANT)
   765  	putattr(ctxt, info, DW_ABRV_INT_CONSTANT, DW_FORM_string, DW_CLS_STRING, int64(len(name)), name)
   766  	putattr(ctxt, info, DW_ABRV_INT_CONSTANT, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, typ)
   767  	putattr(ctxt, info, DW_ABRV_INT_CONSTANT, DW_FORM_sdata, DW_CLS_CONSTANT, val, nil)
   768  }
   769  
   770  // PutRanges writes a range table to sym. All addresses in ranges are
   771  // relative to some base address. If base is not nil, then they're
   772  // relative to the start of base. If base is nil, then the caller must
   773  // arrange a base address some other way (such as a DW_AT_low_pc
   774  // attribute).
   775  func PutRanges(ctxt Context, sym Sym, base Sym, ranges []Range) {
   776  	ps := ctxt.PtrSize()
   777  	// Write ranges.
   778  	// We do not emit base address entries here, even though they would reduce
   779  	// the number of relocations, because dsymutil (which is used on macOS when
   780  	// linking externally) does not support them.
   781  	for _, r := range ranges {
   782  		if base == nil {
   783  			ctxt.AddInt(sym, ps, r.Start)
   784  			ctxt.AddInt(sym, ps, r.End)
   785  		} else {
   786  			ctxt.AddCURelativeAddress(sym, base, r.Start)
   787  			ctxt.AddCURelativeAddress(sym, base, r.End)
   788  		}
   789  	}
   790  	// Write trailer.
   791  	ctxt.AddInt(sym, ps, 0)
   792  	ctxt.AddInt(sym, ps, 0)
   793  }
   794  
   795  // PutFunc writes a DIE for a function to s.
   796  // It also writes child DIEs for each variable in vars.
   797  func PutFunc(ctxt Context, info, loc, ranges, filesym Sym, name string, external bool, startPC Sym, size int64, scopes []Scope) error {
   798  	Uleb128put(ctxt, info, DW_ABRV_FUNCTION)
   799  	putattr(ctxt, info, DW_ABRV_FUNCTION, DW_FORM_string, DW_CLS_STRING, int64(len(name)), name)
   800  	putattr(ctxt, info, DW_ABRV_FUNCTION, DW_FORM_addr, DW_CLS_ADDRESS, 0, startPC)
   801  	putattr(ctxt, info, DW_ABRV_FUNCTION, DW_FORM_addr, DW_CLS_ADDRESS, size, startPC)
   802  	putattr(ctxt, info, DW_ABRV_FUNCTION, DW_FORM_block1, DW_CLS_BLOCK, 1, []byte{DW_OP_call_frame_cfa})
   803  	// DW_AT_decl_file attribute
   804  	ctxt.AddFileRef(info, filesym)
   805  	var ev int64
   806  	if external {
   807  		ev = 1
   808  	}
   809  	putattr(ctxt, info, DW_ABRV_FUNCTION, DW_FORM_flag, DW_CLS_FLAG, ev, 0)
   810  	if len(scopes) > 0 {
   811  		var encbuf [20]byte
   812  		if putscope(ctxt, info, loc, ranges, startPC, 0, scopes, encbuf[:0]) < int32(len(scopes)) {
   813  			return errors.New("multiple toplevel scopes")
   814  		}
   815  	}
   816  	Uleb128put(ctxt, info, 0)
   817  	return nil
   818  }
   819  
   820  func putscope(ctxt Context, info, loc, ranges, startPC Sym, curscope int32, scopes []Scope, encbuf []byte) int32 {
   821  	for _, v := range scopes[curscope].Vars {
   822  		putvar(ctxt, info, loc, v, startPC, encbuf)
   823  	}
   824  	this := curscope
   825  	curscope++
   826  	for curscope < int32(len(scopes)) {
   827  		scope := scopes[curscope]
   828  		if scope.Parent != this {
   829  			return curscope
   830  		}
   831  
   832  		if len(scope.Ranges) == 1 {
   833  			Uleb128put(ctxt, info, DW_ABRV_LEXICAL_BLOCK_SIMPLE)
   834  			putattr(ctxt, info, DW_ABRV_LEXICAL_BLOCK_SIMPLE, DW_FORM_addr, DW_CLS_ADDRESS, scope.Ranges[0].Start, startPC)
   835  			putattr(ctxt, info, DW_ABRV_LEXICAL_BLOCK_SIMPLE, DW_FORM_addr, DW_CLS_ADDRESS, scope.Ranges[0].End, startPC)
   836  		} else {
   837  			Uleb128put(ctxt, info, DW_ABRV_LEXICAL_BLOCK_RANGES)
   838  			putattr(ctxt, info, DW_ABRV_LEXICAL_BLOCK_RANGES, DW_FORM_sec_offset, DW_CLS_PTR, ranges.Len(), ranges)
   839  
   840  			PutRanges(ctxt, ranges, startPC, scope.Ranges)
   841  		}
   842  
   843  		curscope = putscope(ctxt, info, loc, ranges, startPC, curscope, scopes, encbuf)
   844  
   845  		Uleb128put(ctxt, info, 0)
   846  	}
   847  	return curscope
   848  }
   849  
   850  func putvar(ctxt Context, info, loc Sym, v *Var, startPC Sym, encbuf []byte) {
   851  	// If the variable was entirely optimized out, don't emit a location list;
   852  	// convert to an inline abbreviation and emit an empty location.
   853  	missing := false
   854  	switch {
   855  	case v.Abbrev == DW_ABRV_AUTO_LOCLIST && len(v.LocationList) == 0:
   856  		missing = true
   857  		v.Abbrev = DW_ABRV_AUTO
   858  	case v.Abbrev == DW_ABRV_PARAM_LOCLIST && len(v.LocationList) == 0:
   859  		missing = true
   860  		v.Abbrev = DW_ABRV_PARAM
   861  	}
   862  
   863  	Uleb128put(ctxt, info, int64(v.Abbrev))
   864  	putattr(ctxt, info, v.Abbrev, DW_FORM_string, DW_CLS_STRING, int64(len(v.Name)), v.Name)
   865  	if v.Abbrev == DW_ABRV_PARAM || v.Abbrev == DW_ABRV_PARAM_LOCLIST {
   866  		var isReturn int64
   867  		if v.IsReturnValue {
   868  			isReturn = 1
   869  		}
   870  		putattr(ctxt, info, v.Abbrev, DW_FORM_flag, DW_CLS_FLAG, isReturn, nil)
   871  	}
   872  	putattr(ctxt, info, v.Abbrev, DW_FORM_udata, DW_CLS_CONSTANT, int64(v.DeclLine), nil)
   873  	if v.Abbrev == DW_ABRV_AUTO_LOCLIST || v.Abbrev == DW_ABRV_PARAM_LOCLIST {
   874  		putattr(ctxt, info, v.Abbrev, DW_FORM_sec_offset, DW_CLS_PTR, int64(loc.Len()), loc)
   875  		addLocList(ctxt, loc, startPC, v, encbuf)
   876  	} else {
   877  		loc := encbuf[:0]
   878  		switch {
   879  		case missing:
   880  			break // no location
   881  		case v.StackOffset == 0:
   882  			loc = append(loc, DW_OP_call_frame_cfa)
   883  		default:
   884  			loc = append(loc, DW_OP_fbreg)
   885  			loc = AppendSleb128(loc, int64(v.StackOffset))
   886  		}
   887  		putattr(ctxt, info, v.Abbrev, DW_FORM_block1, DW_CLS_BLOCK, int64(len(loc)), loc)
   888  	}
   889  	putattr(ctxt, info, v.Abbrev, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, v.Type)
   890  }
   891  
   892  func addLocList(ctxt Context, listSym, startPC Sym, v *Var, encbuf []byte) {
   893  	// Base address entry: max ptr followed by the base address.
   894  	ctxt.AddInt(listSym, ctxt.PtrSize(), ^0)
   895  	ctxt.AddAddress(listSym, startPC, 0)
   896  	for _, entry := range v.LocationList {
   897  		ctxt.AddInt(listSym, ctxt.PtrSize(), entry.StartPC)
   898  		ctxt.AddInt(listSym, ctxt.PtrSize(), entry.EndPC)
   899  		locBuf := encbuf[:0]
   900  		for _, piece := range entry.Pieces {
   901  			if !piece.Missing {
   902  				if piece.OnStack {
   903  					if piece.StackOffset == 0 {
   904  						locBuf = append(locBuf, DW_OP_call_frame_cfa)
   905  					} else {
   906  						locBuf = append(locBuf, DW_OP_fbreg)
   907  						locBuf = AppendSleb128(locBuf, int64(piece.StackOffset))
   908  					}
   909  				} else {
   910  					if piece.RegNum < 32 {
   911  						locBuf = append(locBuf, DW_OP_reg0+byte(piece.RegNum))
   912  					} else {
   913  						locBuf = append(locBuf, DW_OP_regx)
   914  						locBuf = AppendUleb128(locBuf, uint64(piece.RegNum))
   915  					}
   916  				}
   917  			}
   918  			if len(entry.Pieces) > 1 {
   919  				locBuf = append(locBuf, DW_OP_piece)
   920  				locBuf = AppendUleb128(locBuf, uint64(piece.Length))
   921  			}
   922  		}
   923  		ctxt.AddInt(listSym, 2, int64(len(locBuf)))
   924  		ctxt.AddBytes(listSym, locBuf)
   925  	}
   926  	// End list
   927  	ctxt.AddInt(listSym, ctxt.PtrSize(), 0)
   928  	ctxt.AddInt(listSym, ctxt.PtrSize(), 0)
   929  }
   930  
   931  // VarsByOffset attaches the methods of sort.Interface to []*Var,
   932  // sorting in increasing StackOffset.
   933  type VarsByOffset []*Var
   934  
   935  func (s VarsByOffset) Len() int           { return len(s) }
   936  func (s VarsByOffset) Less(i, j int) bool { return s[i].StackOffset < s[j].StackOffset }
   937  func (s VarsByOffset) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }