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