...

Source file src/github.com/twitchyliquid64/golang-asm/dwarf/dwarf.go

Documentation: github.com/twitchyliquid64/golang-asm/dwarf

     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  	"bytes"
    12  	"github.com/twitchyliquid64/golang-asm/objabi"
    13  	"errors"
    14  	"fmt"
    15  	"os/exec"
    16  	"sort"
    17  	"strconv"
    18  	"strings"
    19  )
    20  
    21  // InfoPrefix is the prefix for all the symbols containing DWARF info entries.
    22  const InfoPrefix = "go.info."
    23  
    24  // ConstInfoPrefix is the prefix for all symbols containing DWARF info
    25  // entries that contain constants.
    26  const ConstInfoPrefix = "go.constinfo."
    27  
    28  // CUInfoPrefix is the prefix for symbols containing information to
    29  // populate the DWARF compilation unit info entries.
    30  const CUInfoPrefix = "go.cuinfo."
    31  
    32  // Used to form the symbol name assigned to the DWARF 'abstract subprogram"
    33  // info entry for a function
    34  const AbstractFuncSuffix = "$abstract"
    35  
    36  // Controls logging/debugging for selected aspects of DWARF subprogram
    37  // generation (functions, scopes).
    38  var logDwarf bool
    39  
    40  // Sym represents a symbol.
    41  type Sym interface {
    42  	Length(dwarfContext interface{}) int64
    43  }
    44  
    45  // A Var represents a local variable or a function parameter.
    46  type Var struct {
    47  	Name          string
    48  	Abbrev        int // Either DW_ABRV_AUTO[_LOCLIST] or DW_ABRV_PARAM[_LOCLIST]
    49  	IsReturnValue bool
    50  	IsInlFormal   bool
    51  	StackOffset   int32
    52  	// This package can't use the ssa package, so it can't mention ssa.FuncDebug,
    53  	// so indirect through a closure.
    54  	PutLocationList func(listSym, startPC Sym)
    55  	Scope           int32
    56  	Type            Sym
    57  	DeclFile        string
    58  	DeclLine        uint
    59  	DeclCol         uint
    60  	InlIndex        int32 // subtract 1 to form real index into InlTree
    61  	ChildIndex      int32 // child DIE index in abstract function
    62  	IsInAbstract    bool  // variable exists in abstract function
    63  }
    64  
    65  // A Scope represents a lexical scope. All variables declared within a
    66  // scope will only be visible to instructions covered by the scope.
    67  // Lexical scopes are contiguous in source files but can end up being
    68  // compiled to discontiguous blocks of instructions in the executable.
    69  // The Ranges field lists all the blocks of instructions that belong
    70  // in this scope.
    71  type Scope struct {
    72  	Parent int32
    73  	Ranges []Range
    74  	Vars   []*Var
    75  }
    76  
    77  // A Range represents a half-open interval [Start, End).
    78  type Range struct {
    79  	Start, End int64
    80  }
    81  
    82  // This container is used by the PutFunc* variants below when
    83  // creating the DWARF subprogram DIE(s) for a function.
    84  type FnState struct {
    85  	Name          string
    86  	Importpath    string
    87  	Info          Sym
    88  	Filesym       Sym
    89  	Loc           Sym
    90  	Ranges        Sym
    91  	Absfn         Sym
    92  	StartPC       Sym
    93  	Size          int64
    94  	External      bool
    95  	Scopes        []Scope
    96  	InlCalls      InlCalls
    97  	UseBASEntries bool
    98  }
    99  
   100  func EnableLogging(doit bool) {
   101  	logDwarf = doit
   102  }
   103  
   104  // UnifyRanges merges the list of ranges of c into the list of ranges of s
   105  func (s *Scope) UnifyRanges(c *Scope) {
   106  	out := make([]Range, 0, len(s.Ranges)+len(c.Ranges))
   107  
   108  	i, j := 0, 0
   109  	for {
   110  		var cur Range
   111  		if i < len(s.Ranges) && j < len(c.Ranges) {
   112  			if s.Ranges[i].Start < c.Ranges[j].Start {
   113  				cur = s.Ranges[i]
   114  				i++
   115  			} else {
   116  				cur = c.Ranges[j]
   117  				j++
   118  			}
   119  		} else if i < len(s.Ranges) {
   120  			cur = s.Ranges[i]
   121  			i++
   122  		} else if j < len(c.Ranges) {
   123  			cur = c.Ranges[j]
   124  			j++
   125  		} else {
   126  			break
   127  		}
   128  
   129  		if n := len(out); n > 0 && cur.Start <= out[n-1].End {
   130  			out[n-1].End = cur.End
   131  		} else {
   132  			out = append(out, cur)
   133  		}
   134  	}
   135  
   136  	s.Ranges = out
   137  }
   138  
   139  // AppendRange adds r to s, if r is non-empty.
   140  // If possible, it extends the last Range in s.Ranges; if not, it creates a new one.
   141  func (s *Scope) AppendRange(r Range) {
   142  	if r.End <= r.Start {
   143  		return
   144  	}
   145  	i := len(s.Ranges)
   146  	if i > 0 && s.Ranges[i-1].End == r.Start {
   147  		s.Ranges[i-1].End = r.End
   148  		return
   149  	}
   150  	s.Ranges = append(s.Ranges, r)
   151  }
   152  
   153  type InlCalls struct {
   154  	Calls []InlCall
   155  }
   156  
   157  type InlCall struct {
   158  	// index into ctx.InlTree describing the call inlined here
   159  	InlIndex int
   160  
   161  	// Symbol of file containing inlined call site (really *obj.LSym).
   162  	CallFile Sym
   163  
   164  	// Line number of inlined call site.
   165  	CallLine uint32
   166  
   167  	// Dwarf abstract subroutine symbol (really *obj.LSym).
   168  	AbsFunSym Sym
   169  
   170  	// Indices of child inlines within Calls array above.
   171  	Children []int
   172  
   173  	// entries in this list are PAUTO's created by the inliner to
   174  	// capture the promoted formals and locals of the inlined callee.
   175  	InlVars []*Var
   176  
   177  	// PC ranges for this inlined call.
   178  	Ranges []Range
   179  
   180  	// Root call (not a child of some other call).
   181  	Root bool
   182  }
   183  
   184  // A Context specifies how to add data to a Sym.
   185  type Context interface {
   186  	PtrSize() int
   187  	AddInt(s Sym, size int, i int64)
   188  	AddBytes(s Sym, b []byte)
   189  	AddAddress(s Sym, t interface{}, ofs int64)
   190  	AddCURelativeAddress(s Sym, t interface{}, ofs int64)
   191  	AddSectionOffset(s Sym, size int, t interface{}, ofs int64)
   192  	AddDWARFAddrSectionOffset(s Sym, t interface{}, ofs int64)
   193  	CurrentOffset(s Sym) int64
   194  	RecordDclReference(from Sym, to Sym, dclIdx int, inlIndex int)
   195  	RecordChildDieOffsets(s Sym, vars []*Var, offsets []int32)
   196  	AddString(s Sym, v string)
   197  	AddFileRef(s Sym, f interface{})
   198  	Logf(format string, args ...interface{})
   199  }
   200  
   201  // AppendUleb128 appends v to b using DWARF's unsigned LEB128 encoding.
   202  func AppendUleb128(b []byte, v uint64) []byte {
   203  	for {
   204  		c := uint8(v & 0x7f)
   205  		v >>= 7
   206  		if v != 0 {
   207  			c |= 0x80
   208  		}
   209  		b = append(b, c)
   210  		if c&0x80 == 0 {
   211  			break
   212  		}
   213  	}
   214  	return b
   215  }
   216  
   217  // AppendSleb128 appends v to b using DWARF's signed LEB128 encoding.
   218  func AppendSleb128(b []byte, v int64) []byte {
   219  	for {
   220  		c := uint8(v & 0x7f)
   221  		s := uint8(v & 0x40)
   222  		v >>= 7
   223  		if (v != -1 || s == 0) && (v != 0 || s != 0) {
   224  			c |= 0x80
   225  		}
   226  		b = append(b, c)
   227  		if c&0x80 == 0 {
   228  			break
   229  		}
   230  	}
   231  	return b
   232  }
   233  
   234  // sevenbits contains all unsigned seven bit numbers, indexed by their value.
   235  var sevenbits = [...]byte{
   236  	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
   237  	0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
   238  	0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
   239  	0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
   240  	0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
   241  	0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
   242  	0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
   243  	0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
   244  }
   245  
   246  // sevenBitU returns the unsigned LEB128 encoding of v if v is seven bits and nil otherwise.
   247  // The contents of the returned slice must not be modified.
   248  func sevenBitU(v int64) []byte {
   249  	if uint64(v) < uint64(len(sevenbits)) {
   250  		return sevenbits[v : v+1]
   251  	}
   252  	return nil
   253  }
   254  
   255  // sevenBitS returns the signed LEB128 encoding of v if v is seven bits and nil otherwise.
   256  // The contents of the returned slice must not be modified.
   257  func sevenBitS(v int64) []byte {
   258  	if uint64(v) <= 63 {
   259  		return sevenbits[v : v+1]
   260  	}
   261  	if uint64(-v) <= 64 {
   262  		return sevenbits[128+v : 128+v+1]
   263  	}
   264  	return nil
   265  }
   266  
   267  // Uleb128put appends v to s using DWARF's unsigned LEB128 encoding.
   268  func Uleb128put(ctxt Context, s Sym, v int64) {
   269  	b := sevenBitU(v)
   270  	if b == nil {
   271  		var encbuf [20]byte
   272  		b = AppendUleb128(encbuf[:0], uint64(v))
   273  	}
   274  	ctxt.AddBytes(s, b)
   275  }
   276  
   277  // Sleb128put appends v to s using DWARF's signed LEB128 encoding.
   278  func Sleb128put(ctxt Context, s Sym, v int64) {
   279  	b := sevenBitS(v)
   280  	if b == nil {
   281  		var encbuf [20]byte
   282  		b = AppendSleb128(encbuf[:0], v)
   283  	}
   284  	ctxt.AddBytes(s, b)
   285  }
   286  
   287  /*
   288   * Defining Abbrevs. This is hardcoded on a per-platform basis (that is,
   289   * each platform will see a fixed abbrev table for all objects); the number
   290   * of abbrev entries is fairly small (compared to C++ objects).  The DWARF
   291   * spec places no restriction on the ordering of attributes in the
   292   * Abbrevs and DIEs, and we will always write them out in the order
   293   * of declaration in the abbrev.
   294   */
   295  type dwAttrForm struct {
   296  	attr uint16
   297  	form uint8
   298  }
   299  
   300  // Go-specific type attributes.
   301  const (
   302  	DW_AT_go_kind = 0x2900
   303  	DW_AT_go_key  = 0x2901
   304  	DW_AT_go_elem = 0x2902
   305  	// Attribute for DW_TAG_member of a struct type.
   306  	// Nonzero value indicates the struct field is an embedded field.
   307  	DW_AT_go_embedded_field = 0x2903
   308  	DW_AT_go_runtime_type   = 0x2904
   309  
   310  	DW_AT_go_package_name = 0x2905 // Attribute for DW_TAG_compile_unit
   311  
   312  	DW_AT_internal_location = 253 // params and locals; not emitted
   313  )
   314  
   315  // Index into the abbrevs table below.
   316  // Keep in sync with ispubname() and ispubtype() in ld/dwarf.go.
   317  // ispubtype considers >= NULLTYPE public
   318  const (
   319  	DW_ABRV_NULL = iota
   320  	DW_ABRV_COMPUNIT
   321  	DW_ABRV_COMPUNIT_TEXTLESS
   322  	DW_ABRV_FUNCTION
   323  	DW_ABRV_FUNCTION_ABSTRACT
   324  	DW_ABRV_FUNCTION_CONCRETE
   325  	DW_ABRV_INLINED_SUBROUTINE
   326  	DW_ABRV_INLINED_SUBROUTINE_RANGES
   327  	DW_ABRV_VARIABLE
   328  	DW_ABRV_INT_CONSTANT
   329  	DW_ABRV_AUTO
   330  	DW_ABRV_AUTO_LOCLIST
   331  	DW_ABRV_AUTO_ABSTRACT
   332  	DW_ABRV_AUTO_CONCRETE
   333  	DW_ABRV_AUTO_CONCRETE_LOCLIST
   334  	DW_ABRV_PARAM
   335  	DW_ABRV_PARAM_LOCLIST
   336  	DW_ABRV_PARAM_ABSTRACT
   337  	DW_ABRV_PARAM_CONCRETE
   338  	DW_ABRV_PARAM_CONCRETE_LOCLIST
   339  	DW_ABRV_LEXICAL_BLOCK_RANGES
   340  	DW_ABRV_LEXICAL_BLOCK_SIMPLE
   341  	DW_ABRV_STRUCTFIELD
   342  	DW_ABRV_FUNCTYPEPARAM
   343  	DW_ABRV_DOTDOTDOT
   344  	DW_ABRV_ARRAYRANGE
   345  	DW_ABRV_NULLTYPE
   346  	DW_ABRV_BASETYPE
   347  	DW_ABRV_ARRAYTYPE
   348  	DW_ABRV_CHANTYPE
   349  	DW_ABRV_FUNCTYPE
   350  	DW_ABRV_IFACETYPE
   351  	DW_ABRV_MAPTYPE
   352  	DW_ABRV_PTRTYPE
   353  	DW_ABRV_BARE_PTRTYPE // only for void*, no DW_AT_type attr to please gdb 6.
   354  	DW_ABRV_SLICETYPE
   355  	DW_ABRV_STRINGTYPE
   356  	DW_ABRV_STRUCTTYPE
   357  	DW_ABRV_TYPEDECL
   358  	DW_NABRV
   359  )
   360  
   361  type dwAbbrev struct {
   362  	tag      uint8
   363  	children uint8
   364  	attr     []dwAttrForm
   365  }
   366  
   367  var abbrevsFinalized bool
   368  
   369  // expandPseudoForm takes an input DW_FORM_xxx value and translates it
   370  // into a platform-appropriate concrete form. Existing concrete/real
   371  // DW_FORM values are left untouched. For the moment the only
   372  // pseudo-form is DW_FORM_udata_pseudo, which gets expanded to
   373  // DW_FORM_data4 on Darwin and DW_FORM_udata everywhere else. See
   374  // issue #31459 for more context.
   375  func expandPseudoForm(form uint8) uint8 {
   376  	// Is this a pseudo-form?
   377  	if form != DW_FORM_udata_pseudo {
   378  		return form
   379  	}
   380  	expandedForm := DW_FORM_udata
   381  	if objabi.GOOS == "darwin" {
   382  		expandedForm = DW_FORM_data4
   383  	}
   384  	return uint8(expandedForm)
   385  }
   386  
   387  // Abbrevs() returns the finalized abbrev array for the platform,
   388  // expanding any DW_FORM pseudo-ops to real values.
   389  func Abbrevs() []dwAbbrev {
   390  	if abbrevsFinalized {
   391  		return abbrevs[:]
   392  	}
   393  	for i := 1; i < DW_NABRV; i++ {
   394  		for j := 0; j < len(abbrevs[i].attr); j++ {
   395  			abbrevs[i].attr[j].form = expandPseudoForm(abbrevs[i].attr[j].form)
   396  		}
   397  	}
   398  	abbrevsFinalized = true
   399  	return abbrevs[:]
   400  }
   401  
   402  // abbrevs is a raw table of abbrev entries; it needs to be post-processed
   403  // by the Abbrevs() function above prior to being consumed, to expand
   404  // the 'pseudo-form' entries below to real DWARF form values.
   405  
   406  var abbrevs = [DW_NABRV]dwAbbrev{
   407  	/* The mandatory DW_ABRV_NULL entry. */
   408  	{0, 0, []dwAttrForm{}},
   409  
   410  	/* COMPUNIT */
   411  	{
   412  		DW_TAG_compile_unit,
   413  		DW_CHILDREN_yes,
   414  		[]dwAttrForm{
   415  			{DW_AT_name, DW_FORM_string},
   416  			{DW_AT_language, DW_FORM_data1},
   417  			{DW_AT_stmt_list, DW_FORM_sec_offset},
   418  			{DW_AT_low_pc, DW_FORM_addr},
   419  			{DW_AT_ranges, DW_FORM_sec_offset},
   420  			{DW_AT_comp_dir, DW_FORM_string},
   421  			{DW_AT_producer, DW_FORM_string},
   422  			{DW_AT_go_package_name, DW_FORM_string},
   423  		},
   424  	},
   425  
   426  	/* COMPUNIT_TEXTLESS */
   427  	{
   428  		DW_TAG_compile_unit,
   429  		DW_CHILDREN_yes,
   430  		[]dwAttrForm{
   431  			{DW_AT_name, DW_FORM_string},
   432  			{DW_AT_language, DW_FORM_data1},
   433  			{DW_AT_comp_dir, DW_FORM_string},
   434  			{DW_AT_producer, DW_FORM_string},
   435  			{DW_AT_go_package_name, DW_FORM_string},
   436  		},
   437  	},
   438  
   439  	/* FUNCTION */
   440  	{
   441  		DW_TAG_subprogram,
   442  		DW_CHILDREN_yes,
   443  		[]dwAttrForm{
   444  			{DW_AT_name, DW_FORM_string},
   445  			{DW_AT_low_pc, DW_FORM_addr},
   446  			{DW_AT_high_pc, DW_FORM_addr},
   447  			{DW_AT_frame_base, DW_FORM_block1},
   448  			{DW_AT_decl_file, DW_FORM_data4},
   449  			{DW_AT_external, DW_FORM_flag},
   450  		},
   451  	},
   452  
   453  	/* FUNCTION_ABSTRACT */
   454  	{
   455  		DW_TAG_subprogram,
   456  		DW_CHILDREN_yes,
   457  		[]dwAttrForm{
   458  			{DW_AT_name, DW_FORM_string},
   459  			{DW_AT_inline, DW_FORM_data1},
   460  			{DW_AT_external, DW_FORM_flag},
   461  		},
   462  	},
   463  
   464  	/* FUNCTION_CONCRETE */
   465  	{
   466  		DW_TAG_subprogram,
   467  		DW_CHILDREN_yes,
   468  		[]dwAttrForm{
   469  			{DW_AT_abstract_origin, DW_FORM_ref_addr},
   470  			{DW_AT_low_pc, DW_FORM_addr},
   471  			{DW_AT_high_pc, DW_FORM_addr},
   472  			{DW_AT_frame_base, DW_FORM_block1},
   473  		},
   474  	},
   475  
   476  	/* INLINED_SUBROUTINE */
   477  	{
   478  		DW_TAG_inlined_subroutine,
   479  		DW_CHILDREN_yes,
   480  		[]dwAttrForm{
   481  			{DW_AT_abstract_origin, DW_FORM_ref_addr},
   482  			{DW_AT_low_pc, DW_FORM_addr},
   483  			{DW_AT_high_pc, DW_FORM_addr},
   484  			{DW_AT_call_file, DW_FORM_data4},
   485  			{DW_AT_call_line, DW_FORM_udata_pseudo}, // pseudo-form
   486  		},
   487  	},
   488  
   489  	/* INLINED_SUBROUTINE_RANGES */
   490  	{
   491  		DW_TAG_inlined_subroutine,
   492  		DW_CHILDREN_yes,
   493  		[]dwAttrForm{
   494  			{DW_AT_abstract_origin, DW_FORM_ref_addr},
   495  			{DW_AT_ranges, DW_FORM_sec_offset},
   496  			{DW_AT_call_file, DW_FORM_data4},
   497  			{DW_AT_call_line, DW_FORM_udata_pseudo}, // pseudo-form
   498  		},
   499  	},
   500  
   501  	/* VARIABLE */
   502  	{
   503  		DW_TAG_variable,
   504  		DW_CHILDREN_no,
   505  		[]dwAttrForm{
   506  			{DW_AT_name, DW_FORM_string},
   507  			{DW_AT_location, DW_FORM_block1},
   508  			{DW_AT_type, DW_FORM_ref_addr},
   509  			{DW_AT_external, DW_FORM_flag},
   510  		},
   511  	},
   512  
   513  	/* INT CONSTANT */
   514  	{
   515  		DW_TAG_constant,
   516  		DW_CHILDREN_no,
   517  		[]dwAttrForm{
   518  			{DW_AT_name, DW_FORM_string},
   519  			{DW_AT_type, DW_FORM_ref_addr},
   520  			{DW_AT_const_value, DW_FORM_sdata},
   521  		},
   522  	},
   523  
   524  	/* AUTO */
   525  	{
   526  		DW_TAG_variable,
   527  		DW_CHILDREN_no,
   528  		[]dwAttrForm{
   529  			{DW_AT_name, DW_FORM_string},
   530  			{DW_AT_decl_line, DW_FORM_udata},
   531  			{DW_AT_type, DW_FORM_ref_addr},
   532  			{DW_AT_location, DW_FORM_block1},
   533  		},
   534  	},
   535  
   536  	/* AUTO_LOCLIST */
   537  	{
   538  		DW_TAG_variable,
   539  		DW_CHILDREN_no,
   540  		[]dwAttrForm{
   541  			{DW_AT_name, DW_FORM_string},
   542  			{DW_AT_decl_line, DW_FORM_udata},
   543  			{DW_AT_type, DW_FORM_ref_addr},
   544  			{DW_AT_location, DW_FORM_sec_offset},
   545  		},
   546  	},
   547  
   548  	/* AUTO_ABSTRACT */
   549  	{
   550  		DW_TAG_variable,
   551  		DW_CHILDREN_no,
   552  		[]dwAttrForm{
   553  			{DW_AT_name, DW_FORM_string},
   554  			{DW_AT_decl_line, DW_FORM_udata},
   555  			{DW_AT_type, DW_FORM_ref_addr},
   556  		},
   557  	},
   558  
   559  	/* AUTO_CONCRETE */
   560  	{
   561  		DW_TAG_variable,
   562  		DW_CHILDREN_no,
   563  		[]dwAttrForm{
   564  			{DW_AT_abstract_origin, DW_FORM_ref_addr},
   565  			{DW_AT_location, DW_FORM_block1},
   566  		},
   567  	},
   568  
   569  	/* AUTO_CONCRETE_LOCLIST */
   570  	{
   571  		DW_TAG_variable,
   572  		DW_CHILDREN_no,
   573  		[]dwAttrForm{
   574  			{DW_AT_abstract_origin, DW_FORM_ref_addr},
   575  			{DW_AT_location, DW_FORM_sec_offset},
   576  		},
   577  	},
   578  
   579  	/* PARAM */
   580  	{
   581  		DW_TAG_formal_parameter,
   582  		DW_CHILDREN_no,
   583  		[]dwAttrForm{
   584  			{DW_AT_name, DW_FORM_string},
   585  			{DW_AT_variable_parameter, DW_FORM_flag},
   586  			{DW_AT_decl_line, DW_FORM_udata},
   587  			{DW_AT_type, DW_FORM_ref_addr},
   588  			{DW_AT_location, DW_FORM_block1},
   589  		},
   590  	},
   591  
   592  	/* PARAM_LOCLIST */
   593  	{
   594  		DW_TAG_formal_parameter,
   595  		DW_CHILDREN_no,
   596  		[]dwAttrForm{
   597  			{DW_AT_name, DW_FORM_string},
   598  			{DW_AT_variable_parameter, DW_FORM_flag},
   599  			{DW_AT_decl_line, DW_FORM_udata},
   600  			{DW_AT_type, DW_FORM_ref_addr},
   601  			{DW_AT_location, DW_FORM_sec_offset},
   602  		},
   603  	},
   604  
   605  	/* PARAM_ABSTRACT */
   606  	{
   607  		DW_TAG_formal_parameter,
   608  		DW_CHILDREN_no,
   609  		[]dwAttrForm{
   610  			{DW_AT_name, DW_FORM_string},
   611  			{DW_AT_variable_parameter, DW_FORM_flag},
   612  			{DW_AT_type, DW_FORM_ref_addr},
   613  		},
   614  	},
   615  
   616  	/* PARAM_CONCRETE */
   617  	{
   618  		DW_TAG_formal_parameter,
   619  		DW_CHILDREN_no,
   620  		[]dwAttrForm{
   621  			{DW_AT_abstract_origin, DW_FORM_ref_addr},
   622  			{DW_AT_location, DW_FORM_block1},
   623  		},
   624  	},
   625  
   626  	/* PARAM_CONCRETE_LOCLIST */
   627  	{
   628  		DW_TAG_formal_parameter,
   629  		DW_CHILDREN_no,
   630  		[]dwAttrForm{
   631  			{DW_AT_abstract_origin, DW_FORM_ref_addr},
   632  			{DW_AT_location, DW_FORM_sec_offset},
   633  		},
   634  	},
   635  
   636  	/* LEXICAL_BLOCK_RANGES */
   637  	{
   638  		DW_TAG_lexical_block,
   639  		DW_CHILDREN_yes,
   640  		[]dwAttrForm{
   641  			{DW_AT_ranges, DW_FORM_sec_offset},
   642  		},
   643  	},
   644  
   645  	/* LEXICAL_BLOCK_SIMPLE */
   646  	{
   647  		DW_TAG_lexical_block,
   648  		DW_CHILDREN_yes,
   649  		[]dwAttrForm{
   650  			{DW_AT_low_pc, DW_FORM_addr},
   651  			{DW_AT_high_pc, DW_FORM_addr},
   652  		},
   653  	},
   654  
   655  	/* STRUCTFIELD */
   656  	{
   657  		DW_TAG_member,
   658  		DW_CHILDREN_no,
   659  		[]dwAttrForm{
   660  			{DW_AT_name, DW_FORM_string},
   661  			{DW_AT_data_member_location, DW_FORM_udata},
   662  			{DW_AT_type, DW_FORM_ref_addr},
   663  			{DW_AT_go_embedded_field, DW_FORM_flag},
   664  		},
   665  	},
   666  
   667  	/* FUNCTYPEPARAM */
   668  	{
   669  		DW_TAG_formal_parameter,
   670  		DW_CHILDREN_no,
   671  
   672  		// No name!
   673  		[]dwAttrForm{
   674  			{DW_AT_type, DW_FORM_ref_addr},
   675  		},
   676  	},
   677  
   678  	/* DOTDOTDOT */
   679  	{
   680  		DW_TAG_unspecified_parameters,
   681  		DW_CHILDREN_no,
   682  		[]dwAttrForm{},
   683  	},
   684  
   685  	/* ARRAYRANGE */
   686  	{
   687  		DW_TAG_subrange_type,
   688  		DW_CHILDREN_no,
   689  
   690  		// No name!
   691  		[]dwAttrForm{
   692  			{DW_AT_type, DW_FORM_ref_addr},
   693  			{DW_AT_count, DW_FORM_udata},
   694  		},
   695  	},
   696  
   697  	// Below here are the types considered public by ispubtype
   698  	/* NULLTYPE */
   699  	{
   700  		DW_TAG_unspecified_type,
   701  		DW_CHILDREN_no,
   702  		[]dwAttrForm{
   703  			{DW_AT_name, DW_FORM_string},
   704  		},
   705  	},
   706  
   707  	/* BASETYPE */
   708  	{
   709  		DW_TAG_base_type,
   710  		DW_CHILDREN_no,
   711  		[]dwAttrForm{
   712  			{DW_AT_name, DW_FORM_string},
   713  			{DW_AT_encoding, DW_FORM_data1},
   714  			{DW_AT_byte_size, DW_FORM_data1},
   715  			{DW_AT_go_kind, DW_FORM_data1},
   716  			{DW_AT_go_runtime_type, DW_FORM_addr},
   717  		},
   718  	},
   719  
   720  	/* ARRAYTYPE */
   721  	// child is subrange with upper bound
   722  	{
   723  		DW_TAG_array_type,
   724  		DW_CHILDREN_yes,
   725  		[]dwAttrForm{
   726  			{DW_AT_name, DW_FORM_string},
   727  			{DW_AT_type, DW_FORM_ref_addr},
   728  			{DW_AT_byte_size, DW_FORM_udata},
   729  			{DW_AT_go_kind, DW_FORM_data1},
   730  			{DW_AT_go_runtime_type, DW_FORM_addr},
   731  		},
   732  	},
   733  
   734  	/* CHANTYPE */
   735  	{
   736  		DW_TAG_typedef,
   737  		DW_CHILDREN_no,
   738  		[]dwAttrForm{
   739  			{DW_AT_name, DW_FORM_string},
   740  			{DW_AT_type, DW_FORM_ref_addr},
   741  			{DW_AT_go_kind, DW_FORM_data1},
   742  			{DW_AT_go_runtime_type, DW_FORM_addr},
   743  			{DW_AT_go_elem, DW_FORM_ref_addr},
   744  		},
   745  	},
   746  
   747  	/* FUNCTYPE */
   748  	{
   749  		DW_TAG_subroutine_type,
   750  		DW_CHILDREN_yes,
   751  		[]dwAttrForm{
   752  			{DW_AT_name, DW_FORM_string},
   753  			{DW_AT_byte_size, DW_FORM_udata},
   754  			{DW_AT_go_kind, DW_FORM_data1},
   755  			{DW_AT_go_runtime_type, DW_FORM_addr},
   756  		},
   757  	},
   758  
   759  	/* IFACETYPE */
   760  	{
   761  		DW_TAG_typedef,
   762  		DW_CHILDREN_yes,
   763  		[]dwAttrForm{
   764  			{DW_AT_name, DW_FORM_string},
   765  			{DW_AT_type, DW_FORM_ref_addr},
   766  			{DW_AT_go_kind, DW_FORM_data1},
   767  			{DW_AT_go_runtime_type, DW_FORM_addr},
   768  		},
   769  	},
   770  
   771  	/* MAPTYPE */
   772  	{
   773  		DW_TAG_typedef,
   774  		DW_CHILDREN_no,
   775  		[]dwAttrForm{
   776  			{DW_AT_name, DW_FORM_string},
   777  			{DW_AT_type, DW_FORM_ref_addr},
   778  			{DW_AT_go_kind, DW_FORM_data1},
   779  			{DW_AT_go_runtime_type, DW_FORM_addr},
   780  			{DW_AT_go_key, DW_FORM_ref_addr},
   781  			{DW_AT_go_elem, DW_FORM_ref_addr},
   782  		},
   783  	},
   784  
   785  	/* PTRTYPE */
   786  	{
   787  		DW_TAG_pointer_type,
   788  		DW_CHILDREN_no,
   789  		[]dwAttrForm{
   790  			{DW_AT_name, DW_FORM_string},
   791  			{DW_AT_type, DW_FORM_ref_addr},
   792  			{DW_AT_go_kind, DW_FORM_data1},
   793  			{DW_AT_go_runtime_type, DW_FORM_addr},
   794  		},
   795  	},
   796  
   797  	/* BARE_PTRTYPE */
   798  	{
   799  		DW_TAG_pointer_type,
   800  		DW_CHILDREN_no,
   801  		[]dwAttrForm{
   802  			{DW_AT_name, DW_FORM_string},
   803  		},
   804  	},
   805  
   806  	/* SLICETYPE */
   807  	{
   808  		DW_TAG_structure_type,
   809  		DW_CHILDREN_yes,
   810  		[]dwAttrForm{
   811  			{DW_AT_name, DW_FORM_string},
   812  			{DW_AT_byte_size, DW_FORM_udata},
   813  			{DW_AT_go_kind, DW_FORM_data1},
   814  			{DW_AT_go_runtime_type, DW_FORM_addr},
   815  			{DW_AT_go_elem, DW_FORM_ref_addr},
   816  		},
   817  	},
   818  
   819  	/* STRINGTYPE */
   820  	{
   821  		DW_TAG_structure_type,
   822  		DW_CHILDREN_yes,
   823  		[]dwAttrForm{
   824  			{DW_AT_name, DW_FORM_string},
   825  			{DW_AT_byte_size, DW_FORM_udata},
   826  			{DW_AT_go_kind, DW_FORM_data1},
   827  			{DW_AT_go_runtime_type, DW_FORM_addr},
   828  		},
   829  	},
   830  
   831  	/* STRUCTTYPE */
   832  	{
   833  		DW_TAG_structure_type,
   834  		DW_CHILDREN_yes,
   835  		[]dwAttrForm{
   836  			{DW_AT_name, DW_FORM_string},
   837  			{DW_AT_byte_size, DW_FORM_udata},
   838  			{DW_AT_go_kind, DW_FORM_data1},
   839  			{DW_AT_go_runtime_type, DW_FORM_addr},
   840  		},
   841  	},
   842  
   843  	/* TYPEDECL */
   844  	{
   845  		DW_TAG_typedef,
   846  		DW_CHILDREN_no,
   847  		[]dwAttrForm{
   848  			{DW_AT_name, DW_FORM_string},
   849  			{DW_AT_type, DW_FORM_ref_addr},
   850  		},
   851  	},
   852  }
   853  
   854  // GetAbbrev returns the contents of the .debug_abbrev section.
   855  func GetAbbrev() []byte {
   856  	abbrevs := Abbrevs()
   857  	var buf []byte
   858  	for i := 1; i < DW_NABRV; i++ {
   859  		// See section 7.5.3
   860  		buf = AppendUleb128(buf, uint64(i))
   861  		buf = AppendUleb128(buf, uint64(abbrevs[i].tag))
   862  		buf = append(buf, abbrevs[i].children)
   863  		for _, f := range abbrevs[i].attr {
   864  			buf = AppendUleb128(buf, uint64(f.attr))
   865  			buf = AppendUleb128(buf, uint64(f.form))
   866  		}
   867  		buf = append(buf, 0, 0)
   868  	}
   869  	return append(buf, 0)
   870  }
   871  
   872  /*
   873   * Debugging Information Entries and their attributes.
   874   */
   875  
   876  // DWAttr represents an attribute of a DWDie.
   877  //
   878  // For DW_CLS_string and _block, value should contain the length, and
   879  // data the data, for _reference, value is 0 and data is a DWDie* to
   880  // the referenced instance, for all others, value is the whole thing
   881  // and data is null.
   882  type DWAttr struct {
   883  	Link  *DWAttr
   884  	Atr   uint16 // DW_AT_
   885  	Cls   uint8  // DW_CLS_
   886  	Value int64
   887  	Data  interface{}
   888  }
   889  
   890  // DWDie represents a DWARF debug info entry.
   891  type DWDie struct {
   892  	Abbrev int
   893  	Link   *DWDie
   894  	Child  *DWDie
   895  	Attr   *DWAttr
   896  	Sym    Sym
   897  }
   898  
   899  func putattr(ctxt Context, s Sym, abbrev int, form int, cls int, value int64, data interface{}) error {
   900  	switch form {
   901  	case DW_FORM_addr: // address
   902  		// Allow nil addresses for DW_AT_go_runtime_type.
   903  		if data == nil && value == 0 {
   904  			ctxt.AddInt(s, ctxt.PtrSize(), 0)
   905  			break
   906  		}
   907  		if cls == DW_CLS_GO_TYPEREF {
   908  			ctxt.AddSectionOffset(s, ctxt.PtrSize(), data, value)
   909  			break
   910  		}
   911  		ctxt.AddAddress(s, data, value)
   912  
   913  	case DW_FORM_block1: // block
   914  		if cls == DW_CLS_ADDRESS {
   915  			ctxt.AddInt(s, 1, int64(1+ctxt.PtrSize()))
   916  			ctxt.AddInt(s, 1, DW_OP_addr)
   917  			ctxt.AddAddress(s, data, 0)
   918  			break
   919  		}
   920  
   921  		value &= 0xff
   922  		ctxt.AddInt(s, 1, value)
   923  		p := data.([]byte)[:value]
   924  		ctxt.AddBytes(s, p)
   925  
   926  	case DW_FORM_block2: // block
   927  		value &= 0xffff
   928  
   929  		ctxt.AddInt(s, 2, value)
   930  		p := data.([]byte)[:value]
   931  		ctxt.AddBytes(s, p)
   932  
   933  	case DW_FORM_block4: // block
   934  		value &= 0xffffffff
   935  
   936  		ctxt.AddInt(s, 4, value)
   937  		p := data.([]byte)[:value]
   938  		ctxt.AddBytes(s, p)
   939  
   940  	case DW_FORM_block: // block
   941  		Uleb128put(ctxt, s, value)
   942  
   943  		p := data.([]byte)[:value]
   944  		ctxt.AddBytes(s, p)
   945  
   946  	case DW_FORM_data1: // constant
   947  		ctxt.AddInt(s, 1, value)
   948  
   949  	case DW_FORM_data2: // constant
   950  		ctxt.AddInt(s, 2, value)
   951  
   952  	case DW_FORM_data4: // constant, {line,loclist,mac,rangelist}ptr
   953  		if cls == DW_CLS_PTR { // DW_AT_stmt_list and DW_AT_ranges
   954  			ctxt.AddDWARFAddrSectionOffset(s, data, value)
   955  			break
   956  		}
   957  		ctxt.AddInt(s, 4, value)
   958  
   959  	case DW_FORM_data8: // constant, {line,loclist,mac,rangelist}ptr
   960  		ctxt.AddInt(s, 8, value)
   961  
   962  	case DW_FORM_sdata: // constant
   963  		Sleb128put(ctxt, s, value)
   964  
   965  	case DW_FORM_udata: // constant
   966  		Uleb128put(ctxt, s, value)
   967  
   968  	case DW_FORM_string: // string
   969  		str := data.(string)
   970  		ctxt.AddString(s, str)
   971  		// TODO(ribrdb): verify padded strings are never used and remove this
   972  		for i := int64(len(str)); i < value; i++ {
   973  			ctxt.AddInt(s, 1, 0)
   974  		}
   975  
   976  	case DW_FORM_flag: // flag
   977  		if value != 0 {
   978  			ctxt.AddInt(s, 1, 1)
   979  		} else {
   980  			ctxt.AddInt(s, 1, 0)
   981  		}
   982  
   983  	// As of DWARF 3 the ref_addr is always 32 bits, unless emitting a large
   984  	// (> 4 GB of debug info aka "64-bit") unit, which we don't implement.
   985  	case DW_FORM_ref_addr: // reference to a DIE in the .info section
   986  		fallthrough
   987  	case DW_FORM_sec_offset: // offset into a DWARF section other than .info
   988  		if data == nil {
   989  			return fmt.Errorf("dwarf: null reference in %d", abbrev)
   990  		}
   991  		ctxt.AddDWARFAddrSectionOffset(s, data, value)
   992  
   993  	case DW_FORM_ref1, // reference within the compilation unit
   994  		DW_FORM_ref2,      // reference
   995  		DW_FORM_ref4,      // reference
   996  		DW_FORM_ref8,      // reference
   997  		DW_FORM_ref_udata, // reference
   998  
   999  		DW_FORM_strp,     // string
  1000  		DW_FORM_indirect: // (see Section 7.5.3)
  1001  		fallthrough
  1002  	default:
  1003  		return fmt.Errorf("dwarf: unsupported attribute form %d / class %d", form, cls)
  1004  	}
  1005  	return nil
  1006  }
  1007  
  1008  // PutAttrs writes the attributes for a DIE to symbol 's'.
  1009  //
  1010  // Note that we can (and do) add arbitrary attributes to a DIE, but
  1011  // only the ones actually listed in the Abbrev will be written out.
  1012  func PutAttrs(ctxt Context, s Sym, abbrev int, attr *DWAttr) {
  1013  	abbrevs := Abbrevs()
  1014  Outer:
  1015  	for _, f := range abbrevs[abbrev].attr {
  1016  		for ap := attr; ap != nil; ap = ap.Link {
  1017  			if ap.Atr == f.attr {
  1018  				putattr(ctxt, s, abbrev, int(f.form), int(ap.Cls), ap.Value, ap.Data)
  1019  				continue Outer
  1020  			}
  1021  		}
  1022  
  1023  		putattr(ctxt, s, abbrev, int(f.form), 0, 0, nil)
  1024  	}
  1025  }
  1026  
  1027  // HasChildren reports whether 'die' uses an abbrev that supports children.
  1028  func HasChildren(die *DWDie) bool {
  1029  	abbrevs := Abbrevs()
  1030  	return abbrevs[die.Abbrev].children != 0
  1031  }
  1032  
  1033  // PutIntConst writes a DIE for an integer constant
  1034  func PutIntConst(ctxt Context, info, typ Sym, name string, val int64) {
  1035  	Uleb128put(ctxt, info, DW_ABRV_INT_CONSTANT)
  1036  	putattr(ctxt, info, DW_ABRV_INT_CONSTANT, DW_FORM_string, DW_CLS_STRING, int64(len(name)), name)
  1037  	putattr(ctxt, info, DW_ABRV_INT_CONSTANT, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, typ)
  1038  	putattr(ctxt, info, DW_ABRV_INT_CONSTANT, DW_FORM_sdata, DW_CLS_CONSTANT, val, nil)
  1039  }
  1040  
  1041  // PutBasedRanges writes a range table to sym. All addresses in ranges are
  1042  // relative to some base address, which must be arranged by the caller
  1043  // (e.g., with a DW_AT_low_pc attribute, or in a BASE-prefixed range).
  1044  func PutBasedRanges(ctxt Context, sym Sym, ranges []Range) {
  1045  	ps := ctxt.PtrSize()
  1046  	// Write ranges.
  1047  	for _, r := range ranges {
  1048  		ctxt.AddInt(sym, ps, r.Start)
  1049  		ctxt.AddInt(sym, ps, r.End)
  1050  	}
  1051  	// Write trailer.
  1052  	ctxt.AddInt(sym, ps, 0)
  1053  	ctxt.AddInt(sym, ps, 0)
  1054  }
  1055  
  1056  // PutRanges writes a range table to s.Ranges.
  1057  // All addresses in ranges are relative to s.base.
  1058  func (s *FnState) PutRanges(ctxt Context, ranges []Range) {
  1059  	ps := ctxt.PtrSize()
  1060  	sym, base := s.Ranges, s.StartPC
  1061  
  1062  	if s.UseBASEntries {
  1063  		// Using a Base Address Selection Entry reduces the number of relocations, but
  1064  		// this is not done on macOS because it is not supported by dsymutil/dwarfdump/lldb
  1065  		ctxt.AddInt(sym, ps, -1)
  1066  		ctxt.AddAddress(sym, base, 0)
  1067  		PutBasedRanges(ctxt, sym, ranges)
  1068  		return
  1069  	}
  1070  
  1071  	// Write ranges full of relocations
  1072  	for _, r := range ranges {
  1073  		ctxt.AddCURelativeAddress(sym, base, r.Start)
  1074  		ctxt.AddCURelativeAddress(sym, base, r.End)
  1075  	}
  1076  	// Write trailer.
  1077  	ctxt.AddInt(sym, ps, 0)
  1078  	ctxt.AddInt(sym, ps, 0)
  1079  }
  1080  
  1081  // Return TRUE if the inlined call in the specified slot is empty,
  1082  // meaning it has a zero-length range (no instructions), and all
  1083  // of its children are empty.
  1084  func isEmptyInlinedCall(slot int, calls *InlCalls) bool {
  1085  	ic := &calls.Calls[slot]
  1086  	if ic.InlIndex == -2 {
  1087  		return true
  1088  	}
  1089  	live := false
  1090  	for _, k := range ic.Children {
  1091  		if !isEmptyInlinedCall(k, calls) {
  1092  			live = true
  1093  		}
  1094  	}
  1095  	if len(ic.Ranges) > 0 {
  1096  		live = true
  1097  	}
  1098  	if !live {
  1099  		ic.InlIndex = -2
  1100  	}
  1101  	return !live
  1102  }
  1103  
  1104  // Slot -1:    return top-level inlines
  1105  // Slot >= 0:  return children of that slot
  1106  func inlChildren(slot int, calls *InlCalls) []int {
  1107  	var kids []int
  1108  	if slot != -1 {
  1109  		for _, k := range calls.Calls[slot].Children {
  1110  			if !isEmptyInlinedCall(k, calls) {
  1111  				kids = append(kids, k)
  1112  			}
  1113  		}
  1114  	} else {
  1115  		for k := 0; k < len(calls.Calls); k += 1 {
  1116  			if calls.Calls[k].Root && !isEmptyInlinedCall(k, calls) {
  1117  				kids = append(kids, k)
  1118  			}
  1119  		}
  1120  	}
  1121  	return kids
  1122  }
  1123  
  1124  func inlinedVarTable(inlcalls *InlCalls) map[*Var]bool {
  1125  	vars := make(map[*Var]bool)
  1126  	for _, ic := range inlcalls.Calls {
  1127  		for _, v := range ic.InlVars {
  1128  			vars[v] = true
  1129  		}
  1130  	}
  1131  	return vars
  1132  }
  1133  
  1134  // The s.Scopes slice contains variables were originally part of the
  1135  // function being emitted, as well as variables that were imported
  1136  // from various callee functions during the inlining process. This
  1137  // function prunes out any variables from the latter category (since
  1138  // they will be emitted as part of DWARF inlined_subroutine DIEs) and
  1139  // then generates scopes for vars in the former category.
  1140  func putPrunedScopes(ctxt Context, s *FnState, fnabbrev int) error {
  1141  	if len(s.Scopes) == 0 {
  1142  		return nil
  1143  	}
  1144  	scopes := make([]Scope, len(s.Scopes), len(s.Scopes))
  1145  	pvars := inlinedVarTable(&s.InlCalls)
  1146  	for k, s := range s.Scopes {
  1147  		var pruned Scope = Scope{Parent: s.Parent, Ranges: s.Ranges}
  1148  		for i := 0; i < len(s.Vars); i++ {
  1149  			_, found := pvars[s.Vars[i]]
  1150  			if !found {
  1151  				pruned.Vars = append(pruned.Vars, s.Vars[i])
  1152  			}
  1153  		}
  1154  		sort.Sort(byChildIndex(pruned.Vars))
  1155  		scopes[k] = pruned
  1156  	}
  1157  	var encbuf [20]byte
  1158  	if putscope(ctxt, s, scopes, 0, fnabbrev, encbuf[:0]) < int32(len(scopes)) {
  1159  		return errors.New("multiple toplevel scopes")
  1160  	}
  1161  	return nil
  1162  }
  1163  
  1164  // Emit DWARF attributes and child DIEs for an 'abstract' subprogram.
  1165  // The abstract subprogram DIE for a function contains its
  1166  // location-independent attributes (name, type, etc). Other instances
  1167  // of the function (any inlined copy of it, or the single out-of-line
  1168  // 'concrete' instance) will contain a pointer back to this abstract
  1169  // DIE (as a space-saving measure, so that name/type etc doesn't have
  1170  // to be repeated for each inlined copy).
  1171  func PutAbstractFunc(ctxt Context, s *FnState) error {
  1172  
  1173  	if logDwarf {
  1174  		ctxt.Logf("PutAbstractFunc(%v)\n", s.Absfn)
  1175  	}
  1176  
  1177  	abbrev := DW_ABRV_FUNCTION_ABSTRACT
  1178  	Uleb128put(ctxt, s.Absfn, int64(abbrev))
  1179  
  1180  	fullname := s.Name
  1181  	if strings.HasPrefix(s.Name, "\"\".") {
  1182  		// Generate a fully qualified name for the function in the
  1183  		// abstract case. This is so as to avoid the need for the
  1184  		// linker to process the DIE with patchDWARFName(); we can't
  1185  		// allow the name attribute of an abstract subprogram DIE to
  1186  		// be rewritten, since it would change the offsets of the
  1187  		// child DIEs (which we're relying on in order for abstract
  1188  		// origin references to work).
  1189  		fullname = objabi.PathToPrefix(s.Importpath) + "." + s.Name[3:]
  1190  	}
  1191  	putattr(ctxt, s.Absfn, abbrev, DW_FORM_string, DW_CLS_STRING, int64(len(fullname)), fullname)
  1192  
  1193  	// DW_AT_inlined value
  1194  	putattr(ctxt, s.Absfn, abbrev, DW_FORM_data1, DW_CLS_CONSTANT, int64(DW_INL_inlined), nil)
  1195  
  1196  	var ev int64
  1197  	if s.External {
  1198  		ev = 1
  1199  	}
  1200  	putattr(ctxt, s.Absfn, abbrev, DW_FORM_flag, DW_CLS_FLAG, ev, 0)
  1201  
  1202  	// Child variables (may be empty)
  1203  	var flattened []*Var
  1204  
  1205  	// This slice will hold the offset in bytes for each child var DIE
  1206  	// with respect to the start of the parent subprogram DIE.
  1207  	var offsets []int32
  1208  
  1209  	// Scopes/vars
  1210  	if len(s.Scopes) > 0 {
  1211  		// For abstract subprogram DIEs we want to flatten out scope info:
  1212  		// lexical scope DIEs contain range and/or hi/lo PC attributes,
  1213  		// which we explicitly don't want for the abstract subprogram DIE.
  1214  		pvars := inlinedVarTable(&s.InlCalls)
  1215  		for _, scope := range s.Scopes {
  1216  			for i := 0; i < len(scope.Vars); i++ {
  1217  				_, found := pvars[scope.Vars[i]]
  1218  				if found || !scope.Vars[i].IsInAbstract {
  1219  					continue
  1220  				}
  1221  				flattened = append(flattened, scope.Vars[i])
  1222  			}
  1223  		}
  1224  		if len(flattened) > 0 {
  1225  			sort.Sort(byChildIndex(flattened))
  1226  
  1227  			if logDwarf {
  1228  				ctxt.Logf("putAbstractScope(%v): vars:", s.Info)
  1229  				for i, v := range flattened {
  1230  					ctxt.Logf(" %d:%s", i, v.Name)
  1231  				}
  1232  				ctxt.Logf("\n")
  1233  			}
  1234  
  1235  			// This slice will hold the offset in bytes for each child
  1236  			// variable DIE with respect to the start of the parent
  1237  			// subprogram DIE.
  1238  			for _, v := range flattened {
  1239  				offsets = append(offsets, int32(ctxt.CurrentOffset(s.Absfn)))
  1240  				putAbstractVar(ctxt, s.Absfn, v)
  1241  			}
  1242  		}
  1243  	}
  1244  	ctxt.RecordChildDieOffsets(s.Absfn, flattened, offsets)
  1245  
  1246  	Uleb128put(ctxt, s.Absfn, 0)
  1247  	return nil
  1248  }
  1249  
  1250  // Emit DWARF attributes and child DIEs for an inlined subroutine. The
  1251  // first attribute of an inlined subroutine DIE is a reference back to
  1252  // its corresponding 'abstract' DIE (containing location-independent
  1253  // attributes such as name, type, etc). Inlined subroutine DIEs can
  1254  // have other inlined subroutine DIEs as children.
  1255  func PutInlinedFunc(ctxt Context, s *FnState, callersym Sym, callIdx int) error {
  1256  	ic := s.InlCalls.Calls[callIdx]
  1257  	callee := ic.AbsFunSym
  1258  
  1259  	abbrev := DW_ABRV_INLINED_SUBROUTINE_RANGES
  1260  	if len(ic.Ranges) == 1 {
  1261  		abbrev = DW_ABRV_INLINED_SUBROUTINE
  1262  	}
  1263  	Uleb128put(ctxt, s.Info, int64(abbrev))
  1264  
  1265  	if logDwarf {
  1266  		ctxt.Logf("PutInlinedFunc(caller=%v,callee=%v,abbrev=%d)\n", callersym, callee, abbrev)
  1267  	}
  1268  
  1269  	// Abstract origin.
  1270  	putattr(ctxt, s.Info, abbrev, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, callee)
  1271  
  1272  	if abbrev == DW_ABRV_INLINED_SUBROUTINE_RANGES {
  1273  		putattr(ctxt, s.Info, abbrev, DW_FORM_sec_offset, DW_CLS_PTR, s.Ranges.Length(ctxt), s.Ranges)
  1274  		s.PutRanges(ctxt, ic.Ranges)
  1275  	} else {
  1276  		st := ic.Ranges[0].Start
  1277  		en := ic.Ranges[0].End
  1278  		putattr(ctxt, s.Info, abbrev, DW_FORM_addr, DW_CLS_ADDRESS, st, s.StartPC)
  1279  		putattr(ctxt, s.Info, abbrev, DW_FORM_addr, DW_CLS_ADDRESS, en, s.StartPC)
  1280  	}
  1281  
  1282  	// Emit call file, line attrs.
  1283  	ctxt.AddFileRef(s.Info, ic.CallFile)
  1284  	form := int(expandPseudoForm(DW_FORM_udata_pseudo))
  1285  	putattr(ctxt, s.Info, abbrev, form, DW_CLS_CONSTANT, int64(ic.CallLine), nil)
  1286  
  1287  	// Variables associated with this inlined routine instance.
  1288  	vars := ic.InlVars
  1289  	sort.Sort(byChildIndex(vars))
  1290  	inlIndex := ic.InlIndex
  1291  	var encbuf [20]byte
  1292  	for _, v := range vars {
  1293  		if !v.IsInAbstract {
  1294  			continue
  1295  		}
  1296  		putvar(ctxt, s, v, callee, abbrev, inlIndex, encbuf[:0])
  1297  	}
  1298  
  1299  	// Children of this inline.
  1300  	for _, sib := range inlChildren(callIdx, &s.InlCalls) {
  1301  		absfn := s.InlCalls.Calls[sib].AbsFunSym
  1302  		err := PutInlinedFunc(ctxt, s, absfn, sib)
  1303  		if err != nil {
  1304  			return err
  1305  		}
  1306  	}
  1307  
  1308  	Uleb128put(ctxt, s.Info, 0)
  1309  	return nil
  1310  }
  1311  
  1312  // Emit DWARF attributes and child DIEs for a 'concrete' subprogram,
  1313  // meaning the out-of-line copy of a function that was inlined at some
  1314  // point during the compilation of its containing package. The first
  1315  // attribute for a concrete DIE is a reference to the 'abstract' DIE
  1316  // for the function (which holds location-independent attributes such
  1317  // as name, type), then the remainder of the attributes are specific
  1318  // to this instance (location, frame base, etc).
  1319  func PutConcreteFunc(ctxt Context, s *FnState) error {
  1320  	if logDwarf {
  1321  		ctxt.Logf("PutConcreteFunc(%v)\n", s.Info)
  1322  	}
  1323  	abbrev := DW_ABRV_FUNCTION_CONCRETE
  1324  	Uleb128put(ctxt, s.Info, int64(abbrev))
  1325  
  1326  	// Abstract origin.
  1327  	putattr(ctxt, s.Info, abbrev, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, s.Absfn)
  1328  
  1329  	// Start/end PC.
  1330  	putattr(ctxt, s.Info, abbrev, DW_FORM_addr, DW_CLS_ADDRESS, 0, s.StartPC)
  1331  	putattr(ctxt, s.Info, abbrev, DW_FORM_addr, DW_CLS_ADDRESS, s.Size, s.StartPC)
  1332  
  1333  	// cfa / frame base
  1334  	putattr(ctxt, s.Info, abbrev, DW_FORM_block1, DW_CLS_BLOCK, 1, []byte{DW_OP_call_frame_cfa})
  1335  
  1336  	// Scopes
  1337  	if err := putPrunedScopes(ctxt, s, abbrev); err != nil {
  1338  		return err
  1339  	}
  1340  
  1341  	// Inlined subroutines.
  1342  	for _, sib := range inlChildren(-1, &s.InlCalls) {
  1343  		absfn := s.InlCalls.Calls[sib].AbsFunSym
  1344  		err := PutInlinedFunc(ctxt, s, absfn, sib)
  1345  		if err != nil {
  1346  			return err
  1347  		}
  1348  	}
  1349  
  1350  	Uleb128put(ctxt, s.Info, 0)
  1351  	return nil
  1352  }
  1353  
  1354  // Emit DWARF attributes and child DIEs for a subprogram. Here
  1355  // 'default' implies that the function in question was not inlined
  1356  // when its containing package was compiled (hence there is no need to
  1357  // emit an abstract version for it to use as a base for inlined
  1358  // routine records).
  1359  func PutDefaultFunc(ctxt Context, s *FnState) error {
  1360  	if logDwarf {
  1361  		ctxt.Logf("PutDefaultFunc(%v)\n", s.Info)
  1362  	}
  1363  	abbrev := DW_ABRV_FUNCTION
  1364  	Uleb128put(ctxt, s.Info, int64(abbrev))
  1365  
  1366  	// Expand '"".' to import path.
  1367  	name := s.Name
  1368  	if s.Importpath != "" {
  1369  		name = strings.Replace(name, "\"\".", objabi.PathToPrefix(s.Importpath)+".", -1)
  1370  	}
  1371  
  1372  	putattr(ctxt, s.Info, DW_ABRV_FUNCTION, DW_FORM_string, DW_CLS_STRING, int64(len(name)), name)
  1373  	putattr(ctxt, s.Info, abbrev, DW_FORM_addr, DW_CLS_ADDRESS, 0, s.StartPC)
  1374  	putattr(ctxt, s.Info, abbrev, DW_FORM_addr, DW_CLS_ADDRESS, s.Size, s.StartPC)
  1375  	putattr(ctxt, s.Info, abbrev, DW_FORM_block1, DW_CLS_BLOCK, 1, []byte{DW_OP_call_frame_cfa})
  1376  	ctxt.AddFileRef(s.Info, s.Filesym)
  1377  
  1378  	var ev int64
  1379  	if s.External {
  1380  		ev = 1
  1381  	}
  1382  	putattr(ctxt, s.Info, abbrev, DW_FORM_flag, DW_CLS_FLAG, ev, 0)
  1383  
  1384  	// Scopes
  1385  	if err := putPrunedScopes(ctxt, s, abbrev); err != nil {
  1386  		return err
  1387  	}
  1388  
  1389  	// Inlined subroutines.
  1390  	for _, sib := range inlChildren(-1, &s.InlCalls) {
  1391  		absfn := s.InlCalls.Calls[sib].AbsFunSym
  1392  		err := PutInlinedFunc(ctxt, s, absfn, sib)
  1393  		if err != nil {
  1394  			return err
  1395  		}
  1396  	}
  1397  
  1398  	Uleb128put(ctxt, s.Info, 0)
  1399  	return nil
  1400  }
  1401  
  1402  func putscope(ctxt Context, s *FnState, scopes []Scope, curscope int32, fnabbrev int, encbuf []byte) int32 {
  1403  
  1404  	if logDwarf {
  1405  		ctxt.Logf("putscope(%v,%d): vars:", s.Info, curscope)
  1406  		for i, v := range scopes[curscope].Vars {
  1407  			ctxt.Logf(" %d:%d:%s", i, v.ChildIndex, v.Name)
  1408  		}
  1409  		ctxt.Logf("\n")
  1410  	}
  1411  
  1412  	for _, v := range scopes[curscope].Vars {
  1413  		putvar(ctxt, s, v, s.Absfn, fnabbrev, -1, encbuf)
  1414  	}
  1415  	this := curscope
  1416  	curscope++
  1417  	for curscope < int32(len(scopes)) {
  1418  		scope := scopes[curscope]
  1419  		if scope.Parent != this {
  1420  			return curscope
  1421  		}
  1422  
  1423  		if len(scopes[curscope].Vars) == 0 {
  1424  			curscope = putscope(ctxt, s, scopes, curscope, fnabbrev, encbuf)
  1425  			continue
  1426  		}
  1427  
  1428  		if len(scope.Ranges) == 1 {
  1429  			Uleb128put(ctxt, s.Info, DW_ABRV_LEXICAL_BLOCK_SIMPLE)
  1430  			putattr(ctxt, s.Info, DW_ABRV_LEXICAL_BLOCK_SIMPLE, DW_FORM_addr, DW_CLS_ADDRESS, scope.Ranges[0].Start, s.StartPC)
  1431  			putattr(ctxt, s.Info, DW_ABRV_LEXICAL_BLOCK_SIMPLE, DW_FORM_addr, DW_CLS_ADDRESS, scope.Ranges[0].End, s.StartPC)
  1432  		} else {
  1433  			Uleb128put(ctxt, s.Info, DW_ABRV_LEXICAL_BLOCK_RANGES)
  1434  			putattr(ctxt, s.Info, DW_ABRV_LEXICAL_BLOCK_RANGES, DW_FORM_sec_offset, DW_CLS_PTR, s.Ranges.Length(ctxt), s.Ranges)
  1435  
  1436  			s.PutRanges(ctxt, scope.Ranges)
  1437  		}
  1438  
  1439  		curscope = putscope(ctxt, s, scopes, curscope, fnabbrev, encbuf)
  1440  
  1441  		Uleb128put(ctxt, s.Info, 0)
  1442  	}
  1443  	return curscope
  1444  }
  1445  
  1446  // Given a default var abbrev code, select corresponding concrete code.
  1447  func concreteVarAbbrev(varAbbrev int) int {
  1448  	switch varAbbrev {
  1449  	case DW_ABRV_AUTO:
  1450  		return DW_ABRV_AUTO_CONCRETE
  1451  	case DW_ABRV_PARAM:
  1452  		return DW_ABRV_PARAM_CONCRETE
  1453  	case DW_ABRV_AUTO_LOCLIST:
  1454  		return DW_ABRV_AUTO_CONCRETE_LOCLIST
  1455  	case DW_ABRV_PARAM_LOCLIST:
  1456  		return DW_ABRV_PARAM_CONCRETE_LOCLIST
  1457  	default:
  1458  		panic("should never happen")
  1459  	}
  1460  }
  1461  
  1462  // Pick the correct abbrev code for variable or parameter DIE.
  1463  func determineVarAbbrev(v *Var, fnabbrev int) (int, bool, bool) {
  1464  	abbrev := v.Abbrev
  1465  
  1466  	// If the variable was entirely optimized out, don't emit a location list;
  1467  	// convert to an inline abbreviation and emit an empty location.
  1468  	missing := false
  1469  	switch {
  1470  	case abbrev == DW_ABRV_AUTO_LOCLIST && v.PutLocationList == nil:
  1471  		missing = true
  1472  		abbrev = DW_ABRV_AUTO
  1473  	case abbrev == DW_ABRV_PARAM_LOCLIST && v.PutLocationList == nil:
  1474  		missing = true
  1475  		abbrev = DW_ABRV_PARAM
  1476  	}
  1477  
  1478  	// Determine whether to use a concrete variable or regular variable DIE.
  1479  	concrete := true
  1480  	switch fnabbrev {
  1481  	case DW_ABRV_FUNCTION:
  1482  		concrete = false
  1483  		break
  1484  	case DW_ABRV_FUNCTION_CONCRETE:
  1485  		// If we're emitting a concrete subprogram DIE and the variable
  1486  		// in question is not part of the corresponding abstract function DIE,
  1487  		// then use the default (non-concrete) abbrev for this param.
  1488  		if !v.IsInAbstract {
  1489  			concrete = false
  1490  		}
  1491  	case DW_ABRV_INLINED_SUBROUTINE, DW_ABRV_INLINED_SUBROUTINE_RANGES:
  1492  	default:
  1493  		panic("should never happen")
  1494  	}
  1495  
  1496  	// Select proper abbrev based on concrete/non-concrete
  1497  	if concrete {
  1498  		abbrev = concreteVarAbbrev(abbrev)
  1499  	}
  1500  
  1501  	return abbrev, missing, concrete
  1502  }
  1503  
  1504  func abbrevUsesLoclist(abbrev int) bool {
  1505  	switch abbrev {
  1506  	case DW_ABRV_AUTO_LOCLIST, DW_ABRV_AUTO_CONCRETE_LOCLIST,
  1507  		DW_ABRV_PARAM_LOCLIST, DW_ABRV_PARAM_CONCRETE_LOCLIST:
  1508  		return true
  1509  	default:
  1510  		return false
  1511  	}
  1512  }
  1513  
  1514  // Emit DWARF attributes for a variable belonging to an 'abstract' subprogram.
  1515  func putAbstractVar(ctxt Context, info Sym, v *Var) {
  1516  	// Remap abbrev
  1517  	abbrev := v.Abbrev
  1518  	switch abbrev {
  1519  	case DW_ABRV_AUTO, DW_ABRV_AUTO_LOCLIST:
  1520  		abbrev = DW_ABRV_AUTO_ABSTRACT
  1521  	case DW_ABRV_PARAM, DW_ABRV_PARAM_LOCLIST:
  1522  		abbrev = DW_ABRV_PARAM_ABSTRACT
  1523  	}
  1524  
  1525  	Uleb128put(ctxt, info, int64(abbrev))
  1526  	putattr(ctxt, info, abbrev, DW_FORM_string, DW_CLS_STRING, int64(len(v.Name)), v.Name)
  1527  
  1528  	// Isreturn attribute if this is a param
  1529  	if abbrev == DW_ABRV_PARAM_ABSTRACT {
  1530  		var isReturn int64
  1531  		if v.IsReturnValue {
  1532  			isReturn = 1
  1533  		}
  1534  		putattr(ctxt, info, abbrev, DW_FORM_flag, DW_CLS_FLAG, isReturn, nil)
  1535  	}
  1536  
  1537  	// Line
  1538  	if abbrev != DW_ABRV_PARAM_ABSTRACT {
  1539  		// See issue 23374 for more on why decl line is skipped for abs params.
  1540  		putattr(ctxt, info, abbrev, DW_FORM_udata, DW_CLS_CONSTANT, int64(v.DeclLine), nil)
  1541  	}
  1542  
  1543  	// Type
  1544  	putattr(ctxt, info, abbrev, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, v.Type)
  1545  
  1546  	// Var has no children => no terminator
  1547  }
  1548  
  1549  func putvar(ctxt Context, s *FnState, v *Var, absfn Sym, fnabbrev, inlIndex int, encbuf []byte) {
  1550  	// Remap abbrev according to parent DIE abbrev
  1551  	abbrev, missing, concrete := determineVarAbbrev(v, fnabbrev)
  1552  
  1553  	Uleb128put(ctxt, s.Info, int64(abbrev))
  1554  
  1555  	// Abstract origin for concrete / inlined case
  1556  	if concrete {
  1557  		// Here we are making a reference to a child DIE of an abstract
  1558  		// function subprogram DIE. The child DIE has no LSym, so instead
  1559  		// after the call to 'putattr' below we make a call to register
  1560  		// the child DIE reference.
  1561  		putattr(ctxt, s.Info, abbrev, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, absfn)
  1562  		ctxt.RecordDclReference(s.Info, absfn, int(v.ChildIndex), inlIndex)
  1563  	} else {
  1564  		// Var name, line for abstract and default cases
  1565  		n := v.Name
  1566  		putattr(ctxt, s.Info, abbrev, DW_FORM_string, DW_CLS_STRING, int64(len(n)), n)
  1567  		if abbrev == DW_ABRV_PARAM || abbrev == DW_ABRV_PARAM_LOCLIST || abbrev == DW_ABRV_PARAM_ABSTRACT {
  1568  			var isReturn int64
  1569  			if v.IsReturnValue {
  1570  				isReturn = 1
  1571  			}
  1572  			putattr(ctxt, s.Info, abbrev, DW_FORM_flag, DW_CLS_FLAG, isReturn, nil)
  1573  		}
  1574  		putattr(ctxt, s.Info, abbrev, DW_FORM_udata, DW_CLS_CONSTANT, int64(v.DeclLine), nil)
  1575  		putattr(ctxt, s.Info, abbrev, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, v.Type)
  1576  	}
  1577  
  1578  	if abbrevUsesLoclist(abbrev) {
  1579  		putattr(ctxt, s.Info, abbrev, DW_FORM_sec_offset, DW_CLS_PTR, s.Loc.Length(ctxt), s.Loc)
  1580  		v.PutLocationList(s.Loc, s.StartPC)
  1581  	} else {
  1582  		loc := encbuf[:0]
  1583  		switch {
  1584  		case missing:
  1585  			break // no location
  1586  		case v.StackOffset == 0:
  1587  			loc = append(loc, DW_OP_call_frame_cfa)
  1588  		default:
  1589  			loc = append(loc, DW_OP_fbreg)
  1590  			loc = AppendSleb128(loc, int64(v.StackOffset))
  1591  		}
  1592  		putattr(ctxt, s.Info, abbrev, DW_FORM_block1, DW_CLS_BLOCK, int64(len(loc)), loc)
  1593  	}
  1594  
  1595  	// Var has no children => no terminator
  1596  }
  1597  
  1598  // VarsByOffset attaches the methods of sort.Interface to []*Var,
  1599  // sorting in increasing StackOffset.
  1600  type VarsByOffset []*Var
  1601  
  1602  func (s VarsByOffset) Len() int           { return len(s) }
  1603  func (s VarsByOffset) Less(i, j int) bool { return s[i].StackOffset < s[j].StackOffset }
  1604  func (s VarsByOffset) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
  1605  
  1606  // byChildIndex implements sort.Interface for []*dwarf.Var by child index.
  1607  type byChildIndex []*Var
  1608  
  1609  func (s byChildIndex) Len() int           { return len(s) }
  1610  func (s byChildIndex) Less(i, j int) bool { return s[i].ChildIndex < s[j].ChildIndex }
  1611  func (s byChildIndex) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
  1612  
  1613  // IsDWARFEnabledOnAIX returns true if DWARF is possible on the
  1614  // current extld.
  1615  // AIX ld doesn't support DWARF with -bnoobjreorder with version
  1616  // prior to 7.2.2.
  1617  func IsDWARFEnabledOnAIXLd(extld string) (bool, error) {
  1618  	out, err := exec.Command(extld, "-Wl,-V").CombinedOutput()
  1619  	if err != nil {
  1620  		// The normal output should display ld version and
  1621  		// then fails because ".main" is not defined:
  1622  		// ld: 0711-317 ERROR: Undefined symbol: .main
  1623  		if !bytes.Contains(out, []byte("0711-317")) {
  1624  			return false, fmt.Errorf("%s -Wl,-V failed: %v\n%s", extld, err, out)
  1625  		}
  1626  	}
  1627  	// gcc -Wl,-V output should be:
  1628  	//   /usr/bin/ld: LD X.X.X(date)
  1629  	//   ...
  1630  	out = bytes.TrimPrefix(out, []byte("/usr/bin/ld: LD "))
  1631  	vers := string(bytes.Split(out, []byte("("))[0])
  1632  	subvers := strings.Split(vers, ".")
  1633  	if len(subvers) != 3 {
  1634  		return false, fmt.Errorf("cannot parse %s -Wl,-V (%s): %v\n", extld, out, err)
  1635  	}
  1636  	if v, err := strconv.Atoi(subvers[0]); err != nil || v < 7 {
  1637  		return false, nil
  1638  	} else if v > 7 {
  1639  		return true, nil
  1640  	}
  1641  	if v, err := strconv.Atoi(subvers[1]); err != nil || v < 2 {
  1642  		return false, nil
  1643  	} else if v > 2 {
  1644  		return true, nil
  1645  	}
  1646  	if v, err := strconv.Atoi(subvers[2]); err != nil || v < 2 {
  1647  		return false, nil
  1648  	}
  1649  	return true, nil
  1650  }
  1651  

View as plain text