Source file src/cmd/internal/dwarf/dwarf.go

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

View as plain text