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