dwarf.go raw

   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