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