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