github.com/Rookout/GoSDK@v0.1.48/pkg/services/assembler/internal/dwarf/dwarf.go (about)

     1  // Copyright 2016 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE.assembler 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  	"errors"
    13  	"fmt"
    14  	"github.com/Rookout/GoSDK/pkg/services/assembler/internal/buildcfg"
    15  	"os/exec"
    16  	"sort"
    17  	"strconv"
    18  	"strings"
    19  
    20  	"github.com/Rookout/GoSDK/pkg/services/assembler/internal/objabi"
    21  )
    22  
    23  
    24  const InfoPrefix = "go:info."
    25  
    26  
    27  
    28  const ConstInfoPrefix = "go:constinfo."
    29  
    30  
    31  
    32  const CUInfoPrefix = "go:cuinfo."
    33  
    34  
    35  
    36  const AbstractFuncSuffix = "$abstract"
    37  
    38  
    39  
    40  var logDwarf bool
    41  
    42  
    43  type Sym interface {
    44  	Length(dwarfContext interface{}) int64
    45  }
    46  
    47  
    48  type Var struct {
    49  	Name          string
    50  	Abbrev        int 
    51  	IsReturnValue bool
    52  	IsInlFormal   bool
    53  	DictIndex     uint16 
    54  	StackOffset   int32
    55  	
    56  	
    57  	PutLocationList func(listSym, startPC Sym)
    58  	Scope           int32
    59  	Type            Sym
    60  	DeclFile        string
    61  	DeclLine        uint
    62  	DeclCol         uint
    63  	InlIndex        int32 
    64  	ChildIndex      int32 
    65  	IsInAbstract    bool  
    66  }
    67  
    68  
    69  
    70  
    71  
    72  
    73  
    74  type Scope struct {
    75  	Parent int32
    76  	Ranges []Range
    77  	Vars   []*Var
    78  }
    79  
    80  
    81  type Range struct {
    82  	Start, End int64
    83  }
    84  
    85  
    86  
    87  type FnState struct {
    88  	Name          string
    89  	Importpath    string
    90  	Info          Sym
    91  	Filesym       Sym
    92  	Loc           Sym
    93  	Ranges        Sym
    94  	Absfn         Sym
    95  	StartPC       Sym
    96  	Size          int64
    97  	StartLine     int32
    98  	External      bool
    99  	Scopes        []Scope
   100  	InlCalls      InlCalls
   101  	UseBASEntries bool
   102  
   103  	dictIndexToOffset []int64
   104  }
   105  
   106  func EnableLogging(doit bool) {
   107  	logDwarf = doit
   108  }
   109  
   110  
   111  
   112  func MergeRanges(in1, in2 []Range) []Range {
   113  	out := make([]Range, 0, len(in1)+len(in2))
   114  	i, j := 0, 0
   115  	for {
   116  		var cur Range
   117  		if i < len(in2) && j < len(in1) {
   118  			if in2[i].Start < in1[j].Start {
   119  				cur = in2[i]
   120  				i++
   121  			} else {
   122  				cur = in1[j]
   123  				j++
   124  			}
   125  		} else if i < len(in2) {
   126  			cur = in2[i]
   127  			i++
   128  		} else if j < len(in1) {
   129  			cur = in1[j]
   130  			j++
   131  		} else {
   132  			break
   133  		}
   134  
   135  		if n := len(out); n > 0 && cur.Start <= out[n-1].End {
   136  			out[n-1].End = cur.End
   137  		} else {
   138  			out = append(out, cur)
   139  		}
   140  	}
   141  
   142  	return out
   143  }
   144  
   145  
   146  func (s *Scope) UnifyRanges(c *Scope) {
   147  	s.Ranges = MergeRanges(s.Ranges, c.Ranges)
   148  }
   149  
   150  
   151  
   152  func (s *Scope) AppendRange(r Range) {
   153  	if r.End <= r.Start {
   154  		return
   155  	}
   156  	i := len(s.Ranges)
   157  	if i > 0 && s.Ranges[i-1].End == r.Start {
   158  		s.Ranges[i-1].End = r.End
   159  		return
   160  	}
   161  	s.Ranges = append(s.Ranges, r)
   162  }
   163  
   164  type InlCalls struct {
   165  	Calls []InlCall
   166  }
   167  
   168  type InlCall struct {
   169  	
   170  	InlIndex int
   171  
   172  	
   173  	CallFile Sym
   174  
   175  	
   176  	CallLine uint32
   177  
   178  	
   179  	AbsFunSym Sym
   180  
   181  	
   182  	Children []int
   183  
   184  	
   185  	
   186  	InlVars []*Var
   187  
   188  	
   189  	Ranges []Range
   190  
   191  	
   192  	Root bool
   193  }
   194  
   195  
   196  type Context interface {
   197  	PtrSize() int
   198  	AddInt(s Sym, size int, i int64)
   199  	AddBytes(s Sym, b []byte)
   200  	AddAddress(s Sym, t interface{}, ofs int64)
   201  	AddCURelativeAddress(s Sym, t interface{}, ofs int64)
   202  	AddSectionOffset(s Sym, size int, t interface{}, ofs int64)
   203  	AddDWARFAddrSectionOffset(s Sym, t interface{}, ofs int64)
   204  	CurrentOffset(s Sym) int64
   205  	RecordDclReference(from Sym, to Sym, dclIdx int, inlIndex int)
   206  	RecordChildDieOffsets(s Sym, vars []*Var, offsets []int32)
   207  	AddString(s Sym, v string)
   208  	AddFileRef(s Sym, f interface{})
   209  	Logf(format string, args ...interface{})
   210  }
   211  
   212  
   213  func AppendUleb128(b []byte, v uint64) []byte {
   214  	for {
   215  		c := uint8(v & 0x7f)
   216  		v >>= 7
   217  		if v != 0 {
   218  			c |= 0x80
   219  		}
   220  		b = append(b, c)
   221  		if c&0x80 == 0 {
   222  			break
   223  		}
   224  	}
   225  	return b
   226  }
   227  
   228  
   229  func AppendSleb128(b []byte, v int64) []byte {
   230  	for {
   231  		c := uint8(v & 0x7f)
   232  		s := uint8(v & 0x40)
   233  		v >>= 7
   234  		if (v != -1 || s == 0) && (v != 0 || s != 0) {
   235  			c |= 0x80
   236  		}
   237  		b = append(b, c)
   238  		if c&0x80 == 0 {
   239  			break
   240  		}
   241  	}
   242  	return b
   243  }
   244  
   245  
   246  var sevenbits = [...]byte{
   247  	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
   248  	0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
   249  	0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
   250  	0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
   251  	0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
   252  	0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
   253  	0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
   254  	0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
   255  }
   256  
   257  
   258  
   259  func sevenBitU(v int64) []byte {
   260  	if uint64(v) < uint64(len(sevenbits)) {
   261  		return sevenbits[v : v+1]
   262  	}
   263  	return nil
   264  }
   265  
   266  
   267  
   268  func sevenBitS(v int64) []byte {
   269  	if uint64(v) <= 63 {
   270  		return sevenbits[v : v+1]
   271  	}
   272  	if uint64(-v) <= 64 {
   273  		return sevenbits[128+v : 128+v+1]
   274  	}
   275  	return nil
   276  }
   277  
   278  
   279  func Uleb128put(ctxt Context, s Sym, v int64) {
   280  	b := sevenBitU(v)
   281  	if b == nil {
   282  		var encbuf [20]byte
   283  		b = AppendUleb128(encbuf[:0], uint64(v))
   284  	}
   285  	ctxt.AddBytes(s, b)
   286  }
   287  
   288  
   289  func Sleb128put(ctxt Context, s Sym, v int64) {
   290  	b := sevenBitS(v)
   291  	if b == nil {
   292  		var encbuf [20]byte
   293  		b = AppendSleb128(encbuf[:0], v)
   294  	}
   295  	ctxt.AddBytes(s, b)
   296  }
   297  
   298  
   299  type dwAttrForm struct {
   300  	attr uint16
   301  	form uint8
   302  }
   303  
   304  
   305  const (
   306  	DW_AT_go_kind = 0x2900
   307  	DW_AT_go_key  = 0x2901
   308  	DW_AT_go_elem = 0x2902
   309  	
   310  	
   311  	DW_AT_go_embedded_field = 0x2903
   312  	DW_AT_go_runtime_type   = 0x2904
   313  
   314  	DW_AT_go_package_name = 0x2905 
   315  	DW_AT_go_dict_index   = 0x2906 
   316  
   317  	DW_AT_internal_location = 253 
   318  )
   319  
   320  
   321  const (
   322  	DW_ABRV_NULL = iota
   323  	DW_ABRV_COMPUNIT
   324  	DW_ABRV_COMPUNIT_TEXTLESS
   325  	DW_ABRV_FUNCTION
   326  	DW_ABRV_WRAPPER
   327  	DW_ABRV_FUNCTION_ABSTRACT
   328  	DW_ABRV_FUNCTION_CONCRETE
   329  	DW_ABRV_WRAPPER_CONCRETE
   330  	DW_ABRV_INLINED_SUBROUTINE
   331  	DW_ABRV_INLINED_SUBROUTINE_RANGES
   332  	DW_ABRV_VARIABLE
   333  	DW_ABRV_INT_CONSTANT
   334  	DW_ABRV_AUTO
   335  	DW_ABRV_AUTO_LOCLIST
   336  	DW_ABRV_AUTO_ABSTRACT
   337  	DW_ABRV_AUTO_CONCRETE
   338  	DW_ABRV_AUTO_CONCRETE_LOCLIST
   339  	DW_ABRV_PARAM
   340  	DW_ABRV_PARAM_LOCLIST
   341  	DW_ABRV_PARAM_ABSTRACT
   342  	DW_ABRV_PARAM_CONCRETE
   343  	DW_ABRV_PARAM_CONCRETE_LOCLIST
   344  	DW_ABRV_LEXICAL_BLOCK_RANGES
   345  	DW_ABRV_LEXICAL_BLOCK_SIMPLE
   346  	DW_ABRV_STRUCTFIELD
   347  	DW_ABRV_FUNCTYPEPARAM
   348  	DW_ABRV_DOTDOTDOT
   349  	DW_ABRV_ARRAYRANGE
   350  	DW_ABRV_NULLTYPE
   351  	DW_ABRV_BASETYPE
   352  	DW_ABRV_ARRAYTYPE
   353  	DW_ABRV_CHANTYPE
   354  	DW_ABRV_FUNCTYPE
   355  	DW_ABRV_IFACETYPE
   356  	DW_ABRV_MAPTYPE
   357  	DW_ABRV_PTRTYPE
   358  	DW_ABRV_BARE_PTRTYPE 
   359  	DW_ABRV_SLICETYPE
   360  	DW_ABRV_STRINGTYPE
   361  	DW_ABRV_STRUCTTYPE
   362  	DW_ABRV_TYPEDECL
   363  	DW_ABRV_DICT_INDEX
   364  	DW_NABRV
   365  )
   366  
   367  type dwAbbrev struct {
   368  	tag      uint8
   369  	children uint8
   370  	attr     []dwAttrForm
   371  }
   372  
   373  var abbrevsFinalized bool
   374  
   375  
   376  
   377  
   378  
   379  
   380  
   381  func expandPseudoForm(form uint8) uint8 {
   382  	
   383  	if form != DW_FORM_udata_pseudo {
   384  		return form
   385  	}
   386  	expandedForm := DW_FORM_udata
   387  	if buildcfg.GOOS == "darwin" || buildcfg.GOOS == "ios" {
   388  		expandedForm = DW_FORM_data4
   389  	}
   390  	return uint8(expandedForm)
   391  }
   392  
   393  
   394  
   395  func Abbrevs() []dwAbbrev {
   396  	if abbrevsFinalized {
   397  		return abbrevs[:]
   398  	}
   399  	for i := 1; i < DW_NABRV; i++ {
   400  		for j := 0; j < len(abbrevs[i].attr); j++ {
   401  			abbrevs[i].attr[j].form = expandPseudoForm(abbrevs[i].attr[j].form)
   402  		}
   403  	}
   404  	abbrevsFinalized = true
   405  	return abbrevs[:]
   406  }
   407  
   408  
   409  
   410  
   411  
   412  var abbrevs = [DW_NABRV]dwAbbrev{
   413  	
   414  	{0, 0, []dwAttrForm{}},
   415  
   416  	
   417  	{
   418  		DW_TAG_compile_unit,
   419  		DW_CHILDREN_yes,
   420  		[]dwAttrForm{
   421  			{DW_AT_name, DW_FORM_string},
   422  			{DW_AT_language, DW_FORM_data1},
   423  			{DW_AT_stmt_list, DW_FORM_sec_offset},
   424  			{DW_AT_low_pc, DW_FORM_addr},
   425  			{DW_AT_ranges, DW_FORM_sec_offset},
   426  			{DW_AT_comp_dir, DW_FORM_string},
   427  			{DW_AT_producer, DW_FORM_string},
   428  			{DW_AT_go_package_name, DW_FORM_string},
   429  		},
   430  	},
   431  
   432  	
   433  	{
   434  		DW_TAG_compile_unit,
   435  		DW_CHILDREN_yes,
   436  		[]dwAttrForm{
   437  			{DW_AT_name, DW_FORM_string},
   438  			{DW_AT_language, DW_FORM_data1},
   439  			{DW_AT_comp_dir, DW_FORM_string},
   440  			{DW_AT_producer, DW_FORM_string},
   441  			{DW_AT_go_package_name, DW_FORM_string},
   442  		},
   443  	},
   444  
   445  	
   446  	{
   447  		DW_TAG_subprogram,
   448  		DW_CHILDREN_yes,
   449  		[]dwAttrForm{
   450  			{DW_AT_name, DW_FORM_string},
   451  			{DW_AT_low_pc, DW_FORM_addr},
   452  			{DW_AT_high_pc, DW_FORM_addr},
   453  			{DW_AT_frame_base, DW_FORM_block1},
   454  			{DW_AT_decl_file, DW_FORM_data4},
   455  			{DW_AT_decl_line, DW_FORM_udata},
   456  			{DW_AT_external, DW_FORM_flag},
   457  		},
   458  	},
   459  
   460  	
   461  	{
   462  		DW_TAG_subprogram,
   463  		DW_CHILDREN_yes,
   464  		[]dwAttrForm{
   465  			{DW_AT_name, DW_FORM_string},
   466  			{DW_AT_low_pc, DW_FORM_addr},
   467  			{DW_AT_high_pc, DW_FORM_addr},
   468  			{DW_AT_frame_base, DW_FORM_block1},
   469  			{DW_AT_trampoline, DW_FORM_flag},
   470  		},
   471  	},
   472  
   473  	
   474  	{
   475  		DW_TAG_subprogram,
   476  		DW_CHILDREN_yes,
   477  		[]dwAttrForm{
   478  			{DW_AT_name, DW_FORM_string},
   479  			{DW_AT_inline, DW_FORM_data1},
   480  			{DW_AT_decl_line, DW_FORM_udata},
   481  			{DW_AT_external, DW_FORM_flag},
   482  		},
   483  	},
   484  
   485  	
   486  	{
   487  		DW_TAG_subprogram,
   488  		DW_CHILDREN_yes,
   489  		[]dwAttrForm{
   490  			{DW_AT_abstract_origin, DW_FORM_ref_addr},
   491  			{DW_AT_low_pc, DW_FORM_addr},
   492  			{DW_AT_high_pc, DW_FORM_addr},
   493  			{DW_AT_frame_base, DW_FORM_block1},
   494  		},
   495  	},
   496  
   497  	
   498  	{
   499  		DW_TAG_subprogram,
   500  		DW_CHILDREN_yes,
   501  		[]dwAttrForm{
   502  			{DW_AT_abstract_origin, DW_FORM_ref_addr},
   503  			{DW_AT_low_pc, DW_FORM_addr},
   504  			{DW_AT_high_pc, DW_FORM_addr},
   505  			{DW_AT_frame_base, DW_FORM_block1},
   506  			{DW_AT_trampoline, DW_FORM_flag},
   507  		},
   508  	},
   509  
   510  	
   511  	{
   512  		DW_TAG_inlined_subroutine,
   513  		DW_CHILDREN_yes,
   514  		[]dwAttrForm{
   515  			{DW_AT_abstract_origin, DW_FORM_ref_addr},
   516  			{DW_AT_low_pc, DW_FORM_addr},
   517  			{DW_AT_high_pc, DW_FORM_addr},
   518  			{DW_AT_call_file, DW_FORM_data4},
   519  			{DW_AT_call_line, DW_FORM_udata_pseudo}, 
   520  		},
   521  	},
   522  
   523  	
   524  	{
   525  		DW_TAG_inlined_subroutine,
   526  		DW_CHILDREN_yes,
   527  		[]dwAttrForm{
   528  			{DW_AT_abstract_origin, DW_FORM_ref_addr},
   529  			{DW_AT_ranges, DW_FORM_sec_offset},
   530  			{DW_AT_call_file, DW_FORM_data4},
   531  			{DW_AT_call_line, DW_FORM_udata_pseudo}, 
   532  		},
   533  	},
   534  
   535  	
   536  	{
   537  		DW_TAG_variable,
   538  		DW_CHILDREN_no,
   539  		[]dwAttrForm{
   540  			{DW_AT_name, DW_FORM_string},
   541  			{DW_AT_location, DW_FORM_block1},
   542  			{DW_AT_type, DW_FORM_ref_addr},
   543  			{DW_AT_external, DW_FORM_flag},
   544  		},
   545  	},
   546  
   547  	
   548  	{
   549  		DW_TAG_constant,
   550  		DW_CHILDREN_no,
   551  		[]dwAttrForm{
   552  			{DW_AT_name, DW_FORM_string},
   553  			{DW_AT_type, DW_FORM_ref_addr},
   554  			{DW_AT_const_value, DW_FORM_sdata},
   555  		},
   556  	},
   557  
   558  	
   559  	{
   560  		DW_TAG_variable,
   561  		DW_CHILDREN_no,
   562  		[]dwAttrForm{
   563  			{DW_AT_name, DW_FORM_string},
   564  			{DW_AT_decl_line, DW_FORM_udata},
   565  			{DW_AT_type, DW_FORM_ref_addr},
   566  			{DW_AT_location, DW_FORM_block1},
   567  		},
   568  	},
   569  
   570  	
   571  	{
   572  		DW_TAG_variable,
   573  		DW_CHILDREN_no,
   574  		[]dwAttrForm{
   575  			{DW_AT_name, DW_FORM_string},
   576  			{DW_AT_decl_line, DW_FORM_udata},
   577  			{DW_AT_type, DW_FORM_ref_addr},
   578  			{DW_AT_location, DW_FORM_sec_offset},
   579  		},
   580  	},
   581  
   582  	
   583  	{
   584  		DW_TAG_variable,
   585  		DW_CHILDREN_no,
   586  		[]dwAttrForm{
   587  			{DW_AT_name, DW_FORM_string},
   588  			{DW_AT_decl_line, DW_FORM_udata},
   589  			{DW_AT_type, DW_FORM_ref_addr},
   590  		},
   591  	},
   592  
   593  	
   594  	{
   595  		DW_TAG_variable,
   596  		DW_CHILDREN_no,
   597  		[]dwAttrForm{
   598  			{DW_AT_abstract_origin, DW_FORM_ref_addr},
   599  			{DW_AT_location, DW_FORM_block1},
   600  		},
   601  	},
   602  
   603  	
   604  	{
   605  		DW_TAG_variable,
   606  		DW_CHILDREN_no,
   607  		[]dwAttrForm{
   608  			{DW_AT_abstract_origin, DW_FORM_ref_addr},
   609  			{DW_AT_location, DW_FORM_sec_offset},
   610  		},
   611  	},
   612  
   613  	
   614  	{
   615  		DW_TAG_formal_parameter,
   616  		DW_CHILDREN_no,
   617  		[]dwAttrForm{
   618  			{DW_AT_name, DW_FORM_string},
   619  			{DW_AT_variable_parameter, DW_FORM_flag},
   620  			{DW_AT_decl_line, DW_FORM_udata},
   621  			{DW_AT_type, DW_FORM_ref_addr},
   622  			{DW_AT_location, DW_FORM_block1},
   623  		},
   624  	},
   625  
   626  	
   627  	{
   628  		DW_TAG_formal_parameter,
   629  		DW_CHILDREN_no,
   630  		[]dwAttrForm{
   631  			{DW_AT_name, DW_FORM_string},
   632  			{DW_AT_variable_parameter, DW_FORM_flag},
   633  			{DW_AT_decl_line, DW_FORM_udata},
   634  			{DW_AT_type, DW_FORM_ref_addr},
   635  			{DW_AT_location, DW_FORM_sec_offset},
   636  		},
   637  	},
   638  
   639  	
   640  	{
   641  		DW_TAG_formal_parameter,
   642  		DW_CHILDREN_no,
   643  		[]dwAttrForm{
   644  			{DW_AT_name, DW_FORM_string},
   645  			{DW_AT_variable_parameter, DW_FORM_flag},
   646  			{DW_AT_type, DW_FORM_ref_addr},
   647  		},
   648  	},
   649  
   650  	
   651  	{
   652  		DW_TAG_formal_parameter,
   653  		DW_CHILDREN_no,
   654  		[]dwAttrForm{
   655  			{DW_AT_abstract_origin, DW_FORM_ref_addr},
   656  			{DW_AT_location, DW_FORM_block1},
   657  		},
   658  	},
   659  
   660  	
   661  	{
   662  		DW_TAG_formal_parameter,
   663  		DW_CHILDREN_no,
   664  		[]dwAttrForm{
   665  			{DW_AT_abstract_origin, DW_FORM_ref_addr},
   666  			{DW_AT_location, DW_FORM_sec_offset},
   667  		},
   668  	},
   669  
   670  	
   671  	{
   672  		DW_TAG_lexical_block,
   673  		DW_CHILDREN_yes,
   674  		[]dwAttrForm{
   675  			{DW_AT_ranges, DW_FORM_sec_offset},
   676  		},
   677  	},
   678  
   679  	
   680  	{
   681  		DW_TAG_lexical_block,
   682  		DW_CHILDREN_yes,
   683  		[]dwAttrForm{
   684  			{DW_AT_low_pc, DW_FORM_addr},
   685  			{DW_AT_high_pc, DW_FORM_addr},
   686  		},
   687  	},
   688  
   689  	
   690  	{
   691  		DW_TAG_member,
   692  		DW_CHILDREN_no,
   693  		[]dwAttrForm{
   694  			{DW_AT_name, DW_FORM_string},
   695  			{DW_AT_data_member_location, DW_FORM_udata},
   696  			{DW_AT_type, DW_FORM_ref_addr},
   697  			{DW_AT_go_embedded_field, DW_FORM_flag},
   698  		},
   699  	},
   700  
   701  	
   702  	{
   703  		DW_TAG_formal_parameter,
   704  		DW_CHILDREN_no,
   705  
   706  		
   707  		[]dwAttrForm{
   708  			{DW_AT_type, DW_FORM_ref_addr},
   709  		},
   710  	},
   711  
   712  	
   713  	{
   714  		DW_TAG_unspecified_parameters,
   715  		DW_CHILDREN_no,
   716  		[]dwAttrForm{},
   717  	},
   718  
   719  	
   720  	{
   721  		DW_TAG_subrange_type,
   722  		DW_CHILDREN_no,
   723  
   724  		
   725  		[]dwAttrForm{
   726  			{DW_AT_type, DW_FORM_ref_addr},
   727  			{DW_AT_count, DW_FORM_udata},
   728  		},
   729  	},
   730  
   731  	
   732  	
   733  	{
   734  		DW_TAG_unspecified_type,
   735  		DW_CHILDREN_no,
   736  		[]dwAttrForm{
   737  			{DW_AT_name, DW_FORM_string},
   738  		},
   739  	},
   740  
   741  	
   742  	{
   743  		DW_TAG_base_type,
   744  		DW_CHILDREN_no,
   745  		[]dwAttrForm{
   746  			{DW_AT_name, DW_FORM_string},
   747  			{DW_AT_encoding, DW_FORM_data1},
   748  			{DW_AT_byte_size, DW_FORM_data1},
   749  			{DW_AT_go_kind, DW_FORM_data1},
   750  			{DW_AT_go_runtime_type, DW_FORM_addr},
   751  		},
   752  	},
   753  
   754  	
   755  	
   756  	{
   757  		DW_TAG_array_type,
   758  		DW_CHILDREN_yes,
   759  		[]dwAttrForm{
   760  			{DW_AT_name, DW_FORM_string},
   761  			{DW_AT_type, DW_FORM_ref_addr},
   762  			{DW_AT_byte_size, DW_FORM_udata},
   763  			{DW_AT_go_kind, DW_FORM_data1},
   764  			{DW_AT_go_runtime_type, DW_FORM_addr},
   765  		},
   766  	},
   767  
   768  	
   769  	{
   770  		DW_TAG_typedef,
   771  		DW_CHILDREN_no,
   772  		[]dwAttrForm{
   773  			{DW_AT_name, DW_FORM_string},
   774  			{DW_AT_type, DW_FORM_ref_addr},
   775  			{DW_AT_go_kind, DW_FORM_data1},
   776  			{DW_AT_go_runtime_type, DW_FORM_addr},
   777  			{DW_AT_go_elem, DW_FORM_ref_addr},
   778  		},
   779  	},
   780  
   781  	
   782  	{
   783  		DW_TAG_subroutine_type,
   784  		DW_CHILDREN_yes,
   785  		[]dwAttrForm{
   786  			{DW_AT_name, DW_FORM_string},
   787  			{DW_AT_byte_size, DW_FORM_udata},
   788  			{DW_AT_go_kind, DW_FORM_data1},
   789  			{DW_AT_go_runtime_type, DW_FORM_addr},
   790  		},
   791  	},
   792  
   793  	
   794  	{
   795  		DW_TAG_typedef,
   796  		DW_CHILDREN_yes,
   797  		[]dwAttrForm{
   798  			{DW_AT_name, DW_FORM_string},
   799  			{DW_AT_type, DW_FORM_ref_addr},
   800  			{DW_AT_go_kind, DW_FORM_data1},
   801  			{DW_AT_go_runtime_type, DW_FORM_addr},
   802  		},
   803  	},
   804  
   805  	
   806  	{
   807  		DW_TAG_typedef,
   808  		DW_CHILDREN_no,
   809  		[]dwAttrForm{
   810  			{DW_AT_name, DW_FORM_string},
   811  			{DW_AT_type, DW_FORM_ref_addr},
   812  			{DW_AT_go_kind, DW_FORM_data1},
   813  			{DW_AT_go_runtime_type, DW_FORM_addr},
   814  			{DW_AT_go_key, DW_FORM_ref_addr},
   815  			{DW_AT_go_elem, DW_FORM_ref_addr},
   816  		},
   817  	},
   818  
   819  	
   820  	{
   821  		DW_TAG_pointer_type,
   822  		DW_CHILDREN_no,
   823  		[]dwAttrForm{
   824  			{DW_AT_name, DW_FORM_string},
   825  			{DW_AT_type, DW_FORM_ref_addr},
   826  			{DW_AT_go_kind, DW_FORM_data1},
   827  			{DW_AT_go_runtime_type, DW_FORM_addr},
   828  		},
   829  	},
   830  
   831  	
   832  	{
   833  		DW_TAG_pointer_type,
   834  		DW_CHILDREN_no,
   835  		[]dwAttrForm{
   836  			{DW_AT_name, DW_FORM_string},
   837  		},
   838  	},
   839  
   840  	
   841  	{
   842  		DW_TAG_structure_type,
   843  		DW_CHILDREN_yes,
   844  		[]dwAttrForm{
   845  			{DW_AT_name, DW_FORM_string},
   846  			{DW_AT_byte_size, DW_FORM_udata},
   847  			{DW_AT_go_kind, DW_FORM_data1},
   848  			{DW_AT_go_runtime_type, DW_FORM_addr},
   849  			{DW_AT_go_elem, DW_FORM_ref_addr},
   850  		},
   851  	},
   852  
   853  	
   854  	{
   855  		DW_TAG_structure_type,
   856  		DW_CHILDREN_yes,
   857  		[]dwAttrForm{
   858  			{DW_AT_name, DW_FORM_string},
   859  			{DW_AT_byte_size, DW_FORM_udata},
   860  			{DW_AT_go_kind, DW_FORM_data1},
   861  			{DW_AT_go_runtime_type, DW_FORM_addr},
   862  		},
   863  	},
   864  
   865  	
   866  	{
   867  		DW_TAG_structure_type,
   868  		DW_CHILDREN_yes,
   869  		[]dwAttrForm{
   870  			{DW_AT_name, DW_FORM_string},
   871  			{DW_AT_byte_size, DW_FORM_udata},
   872  			{DW_AT_go_kind, DW_FORM_data1},
   873  			{DW_AT_go_runtime_type, DW_FORM_addr},
   874  		},
   875  	},
   876  
   877  	
   878  	{
   879  		DW_TAG_typedef,
   880  		DW_CHILDREN_no,
   881  		[]dwAttrForm{
   882  			{DW_AT_name, DW_FORM_string},
   883  			{DW_AT_type, DW_FORM_ref_addr},
   884  		},
   885  	},
   886  
   887  	
   888  	{
   889  		DW_TAG_typedef,
   890  		DW_CHILDREN_no,
   891  		[]dwAttrForm{
   892  			{DW_AT_name, DW_FORM_string},
   893  			{DW_AT_type, DW_FORM_ref_addr},
   894  			{DW_AT_go_dict_index, DW_FORM_udata},
   895  		},
   896  	},
   897  }
   898  
   899  
   900  func GetAbbrev() []byte {
   901  	abbrevs := Abbrevs()
   902  	var buf []byte
   903  	for i := 1; i < DW_NABRV; i++ {
   904  		
   905  		buf = AppendUleb128(buf, uint64(i))
   906  		buf = AppendUleb128(buf, uint64(abbrevs[i].tag))
   907  		buf = append(buf, abbrevs[i].children)
   908  		for _, f := range abbrevs[i].attr {
   909  			buf = AppendUleb128(buf, uint64(f.attr))
   910  			buf = AppendUleb128(buf, uint64(f.form))
   911  		}
   912  		buf = append(buf, 0, 0)
   913  	}
   914  	return append(buf, 0)
   915  }
   916  
   917  
   918  
   919  
   920  
   921  
   922  
   923  
   924  
   925  type DWAttr struct {
   926  	Link  *DWAttr
   927  	Atr   uint16 
   928  	Cls   uint8  
   929  	Value int64
   930  	Data  interface{}
   931  }
   932  
   933  
   934  type DWDie struct {
   935  	Abbrev int
   936  	Link   *DWDie
   937  	Child  *DWDie
   938  	Attr   *DWAttr
   939  	Sym    Sym
   940  }
   941  
   942  func putattr(ctxt Context, s Sym, abbrev int, form int, cls int, value int64, data interface{}) error {
   943  	switch form {
   944  	case DW_FORM_addr: 
   945  		
   946  		if data == nil && value == 0 {
   947  			ctxt.AddInt(s, ctxt.PtrSize(), 0)
   948  			break
   949  		}
   950  		if cls == DW_CLS_GO_TYPEREF {
   951  			ctxt.AddSectionOffset(s, ctxt.PtrSize(), data, value)
   952  			break
   953  		}
   954  		ctxt.AddAddress(s, data, value)
   955  
   956  	case DW_FORM_block1: 
   957  		if cls == DW_CLS_ADDRESS {
   958  			ctxt.AddInt(s, 1, int64(1+ctxt.PtrSize()))
   959  			ctxt.AddInt(s, 1, DW_OP_addr)
   960  			ctxt.AddAddress(s, data, 0)
   961  			break
   962  		}
   963  
   964  		value &= 0xff
   965  		ctxt.AddInt(s, 1, value)
   966  		p := data.([]byte)[:value]
   967  		ctxt.AddBytes(s, p)
   968  
   969  	case DW_FORM_block2: 
   970  		value &= 0xffff
   971  
   972  		ctxt.AddInt(s, 2, value)
   973  		p := data.([]byte)[:value]
   974  		ctxt.AddBytes(s, p)
   975  
   976  	case DW_FORM_block4: 
   977  		value &= 0xffffffff
   978  
   979  		ctxt.AddInt(s, 4, value)
   980  		p := data.([]byte)[:value]
   981  		ctxt.AddBytes(s, p)
   982  
   983  	case DW_FORM_block: 
   984  		Uleb128put(ctxt, s, value)
   985  
   986  		p := data.([]byte)[:value]
   987  		ctxt.AddBytes(s, p)
   988  
   989  	case DW_FORM_data1: 
   990  		ctxt.AddInt(s, 1, value)
   991  
   992  	case DW_FORM_data2: 
   993  		ctxt.AddInt(s, 2, value)
   994  
   995  	case DW_FORM_data4: 
   996  		if cls == DW_CLS_PTR { 
   997  			ctxt.AddDWARFAddrSectionOffset(s, data, value)
   998  			break
   999  		}
  1000  		ctxt.AddInt(s, 4, value)
  1001  
  1002  	case DW_FORM_data8: 
  1003  		ctxt.AddInt(s, 8, value)
  1004  
  1005  	case DW_FORM_sdata: 
  1006  		Sleb128put(ctxt, s, value)
  1007  
  1008  	case DW_FORM_udata: 
  1009  		Uleb128put(ctxt, s, value)
  1010  
  1011  	case DW_FORM_string: 
  1012  		str := data.(string)
  1013  		ctxt.AddString(s, str)
  1014  		
  1015  		for i := int64(len(str)); i < value; i++ {
  1016  			ctxt.AddInt(s, 1, 0)
  1017  		}
  1018  
  1019  	case DW_FORM_flag: 
  1020  		if value != 0 {
  1021  			ctxt.AddInt(s, 1, 1)
  1022  		} else {
  1023  			ctxt.AddInt(s, 1, 0)
  1024  		}
  1025  
  1026  	
  1027  	
  1028  	case DW_FORM_ref_addr: 
  1029  		fallthrough
  1030  	case DW_FORM_sec_offset: 
  1031  		if data == nil {
  1032  			return fmt.Errorf("dwarf: null reference in %d", abbrev)
  1033  		}
  1034  		ctxt.AddDWARFAddrSectionOffset(s, data, value)
  1035  
  1036  	case DW_FORM_ref1, 
  1037  		DW_FORM_ref2,      
  1038  		DW_FORM_ref4,      
  1039  		DW_FORM_ref8,      
  1040  		DW_FORM_ref_udata, 
  1041  
  1042  		DW_FORM_strp,     
  1043  		DW_FORM_indirect: 
  1044  		fallthrough
  1045  	default:
  1046  		return fmt.Errorf("dwarf: unsupported attribute form %d / class %d", form, cls)
  1047  	}
  1048  	return nil
  1049  }
  1050  
  1051  
  1052  
  1053  
  1054  
  1055  func PutAttrs(ctxt Context, s Sym, abbrev int, attr *DWAttr) {
  1056  	abbrevs := Abbrevs()
  1057  Outer:
  1058  	for _, f := range abbrevs[abbrev].attr {
  1059  		for ap := attr; ap != nil; ap = ap.Link {
  1060  			if ap.Atr == f.attr {
  1061  				putattr(ctxt, s, abbrev, int(f.form), int(ap.Cls), ap.Value, ap.Data)
  1062  				continue Outer
  1063  			}
  1064  		}
  1065  
  1066  		putattr(ctxt, s, abbrev, int(f.form), 0, 0, nil)
  1067  	}
  1068  }
  1069  
  1070  
  1071  func HasChildren(die *DWDie) bool {
  1072  	abbrevs := Abbrevs()
  1073  	return abbrevs[die.Abbrev].children != 0
  1074  }
  1075  
  1076  
  1077  func PutIntConst(ctxt Context, info, typ Sym, name string, val int64) {
  1078  	Uleb128put(ctxt, info, DW_ABRV_INT_CONSTANT)
  1079  	putattr(ctxt, info, DW_ABRV_INT_CONSTANT, DW_FORM_string, DW_CLS_STRING, int64(len(name)), name)
  1080  	putattr(ctxt, info, DW_ABRV_INT_CONSTANT, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, typ)
  1081  	putattr(ctxt, info, DW_ABRV_INT_CONSTANT, DW_FORM_sdata, DW_CLS_CONSTANT, val, nil)
  1082  }
  1083  
  1084  
  1085  func PutGlobal(ctxt Context, info, typ, gvar Sym, name string) {
  1086  	Uleb128put(ctxt, info, DW_ABRV_VARIABLE)
  1087  	putattr(ctxt, info, DW_ABRV_VARIABLE, DW_FORM_string, DW_CLS_STRING, int64(len(name)), name)
  1088  	putattr(ctxt, info, DW_ABRV_VARIABLE, DW_FORM_block1, DW_CLS_ADDRESS, 0, gvar)
  1089  	putattr(ctxt, info, DW_ABRV_VARIABLE, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, typ)
  1090  	putattr(ctxt, info, DW_ABRV_VARIABLE, DW_FORM_flag, DW_CLS_FLAG, 1, nil)
  1091  }
  1092  
  1093  
  1094  
  1095  
  1096  func PutBasedRanges(ctxt Context, sym Sym, ranges []Range) {
  1097  	ps := ctxt.PtrSize()
  1098  	
  1099  	for _, r := range ranges {
  1100  		ctxt.AddInt(sym, ps, r.Start)
  1101  		ctxt.AddInt(sym, ps, r.End)
  1102  	}
  1103  	
  1104  	ctxt.AddInt(sym, ps, 0)
  1105  	ctxt.AddInt(sym, ps, 0)
  1106  }
  1107  
  1108  
  1109  
  1110  func (s *FnState) PutRanges(ctxt Context, ranges []Range) {
  1111  	ps := ctxt.PtrSize()
  1112  	sym, base := s.Ranges, s.StartPC
  1113  
  1114  	if s.UseBASEntries {
  1115  		
  1116  		
  1117  		ctxt.AddInt(sym, ps, -1)
  1118  		ctxt.AddAddress(sym, base, 0)
  1119  		PutBasedRanges(ctxt, sym, ranges)
  1120  		return
  1121  	}
  1122  
  1123  	
  1124  	for _, r := range ranges {
  1125  		ctxt.AddCURelativeAddress(sym, base, r.Start)
  1126  		ctxt.AddCURelativeAddress(sym, base, r.End)
  1127  	}
  1128  	
  1129  	ctxt.AddInt(sym, ps, 0)
  1130  	ctxt.AddInt(sym, ps, 0)
  1131  }
  1132  
  1133  
  1134  
  1135  
  1136  func isEmptyInlinedCall(slot int, calls *InlCalls) bool {
  1137  	ic := &calls.Calls[slot]
  1138  	if ic.InlIndex == -2 {
  1139  		return true
  1140  	}
  1141  	live := false
  1142  	for _, k := range ic.Children {
  1143  		if !isEmptyInlinedCall(k, calls) {
  1144  			live = true
  1145  		}
  1146  	}
  1147  	if len(ic.Ranges) > 0 {
  1148  		live = true
  1149  	}
  1150  	if !live {
  1151  		ic.InlIndex = -2
  1152  	}
  1153  	return !live
  1154  }
  1155  
  1156  
  1157  
  1158  func inlChildren(slot int, calls *InlCalls) []int {
  1159  	var kids []int
  1160  	if slot != -1 {
  1161  		for _, k := range calls.Calls[slot].Children {
  1162  			if !isEmptyInlinedCall(k, calls) {
  1163  				kids = append(kids, k)
  1164  			}
  1165  		}
  1166  	} else {
  1167  		for k := 0; k < len(calls.Calls); k += 1 {
  1168  			if calls.Calls[k].Root && !isEmptyInlinedCall(k, calls) {
  1169  				kids = append(kids, k)
  1170  			}
  1171  		}
  1172  	}
  1173  	return kids
  1174  }
  1175  
  1176  func inlinedVarTable(inlcalls *InlCalls) map[*Var]bool {
  1177  	vars := make(map[*Var]bool)
  1178  	for _, ic := range inlcalls.Calls {
  1179  		for _, v := range ic.InlVars {
  1180  			vars[v] = true
  1181  		}
  1182  	}
  1183  	return vars
  1184  }
  1185  
  1186  
  1187  
  1188  
  1189  
  1190  
  1191  
  1192  func putPrunedScopes(ctxt Context, s *FnState, fnabbrev int) error {
  1193  	if len(s.Scopes) == 0 {
  1194  		return nil
  1195  	}
  1196  	scopes := make([]Scope, len(s.Scopes), len(s.Scopes))
  1197  	pvars := inlinedVarTable(&s.InlCalls)
  1198  	for k, s := range s.Scopes {
  1199  		var pruned Scope = Scope{Parent: s.Parent, Ranges: s.Ranges}
  1200  		for i := 0; i < len(s.Vars); i++ {
  1201  			_, found := pvars[s.Vars[i]]
  1202  			if !found {
  1203  				pruned.Vars = append(pruned.Vars, s.Vars[i])
  1204  			}
  1205  		}
  1206  		sort.Sort(byChildIndex(pruned.Vars))
  1207  		scopes[k] = pruned
  1208  	}
  1209  
  1210  	s.dictIndexToOffset = putparamtypes(ctxt, s, scopes, fnabbrev)
  1211  
  1212  	var encbuf [20]byte
  1213  	if putscope(ctxt, s, scopes, 0, fnabbrev, encbuf[:0]) < int32(len(scopes)) {
  1214  		return errors.New("multiple toplevel scopes")
  1215  	}
  1216  	return nil
  1217  }
  1218  
  1219  
  1220  
  1221  
  1222  
  1223  
  1224  
  1225  
  1226  func PutAbstractFunc(ctxt Context, s *FnState) error {
  1227  
  1228  	if logDwarf {
  1229  		ctxt.Logf("PutAbstractFunc(%v)\n", s.Absfn)
  1230  	}
  1231  
  1232  	abbrev := DW_ABRV_FUNCTION_ABSTRACT
  1233  	Uleb128put(ctxt, s.Absfn, int64(abbrev))
  1234  
  1235  	fullname := s.Name
  1236  	if strings.HasPrefix(s.Name, "\"\".") {
  1237  		
  1238  		
  1239  		
  1240  		
  1241  		
  1242  		
  1243  		
  1244  		fullname = objabi.PathToPrefix(s.Importpath) + "." + s.Name[3:]
  1245  	}
  1246  	putattr(ctxt, s.Absfn, abbrev, DW_FORM_string, DW_CLS_STRING, int64(len(fullname)), fullname)
  1247  
  1248  	
  1249  	putattr(ctxt, s.Absfn, abbrev, DW_FORM_data1, DW_CLS_CONSTANT, int64(DW_INL_inlined), nil)
  1250  
  1251  	putattr(ctxt, s.Absfn, abbrev, DW_FORM_udata, DW_CLS_CONSTANT, int64(s.StartLine), nil)
  1252  
  1253  	var ev int64
  1254  	if s.External {
  1255  		ev = 1
  1256  	}
  1257  	putattr(ctxt, s.Absfn, abbrev, DW_FORM_flag, DW_CLS_FLAG, ev, 0)
  1258  
  1259  	
  1260  	var flattened []*Var
  1261  
  1262  	
  1263  	
  1264  	var offsets []int32
  1265  
  1266  	
  1267  	if len(s.Scopes) > 0 {
  1268  		
  1269  		
  1270  		
  1271  		pvars := inlinedVarTable(&s.InlCalls)
  1272  		for _, scope := range s.Scopes {
  1273  			for i := 0; i < len(scope.Vars); i++ {
  1274  				_, found := pvars[scope.Vars[i]]
  1275  				if found || !scope.Vars[i].IsInAbstract {
  1276  					continue
  1277  				}
  1278  				flattened = append(flattened, scope.Vars[i])
  1279  			}
  1280  		}
  1281  		if len(flattened) > 0 {
  1282  			sort.Sort(byChildIndex(flattened))
  1283  
  1284  			if logDwarf {
  1285  				ctxt.Logf("putAbstractScope(%v): vars:", s.Info)
  1286  				for i, v := range flattened {
  1287  					ctxt.Logf(" %d:%s", i, v.Name)
  1288  				}
  1289  				ctxt.Logf("\n")
  1290  			}
  1291  
  1292  			
  1293  			
  1294  			
  1295  			for _, v := range flattened {
  1296  				offsets = append(offsets, int32(ctxt.CurrentOffset(s.Absfn)))
  1297  				putAbstractVar(ctxt, s.Absfn, v)
  1298  			}
  1299  		}
  1300  	}
  1301  	ctxt.RecordChildDieOffsets(s.Absfn, flattened, offsets)
  1302  
  1303  	Uleb128put(ctxt, s.Absfn, 0)
  1304  	return nil
  1305  }
  1306  
  1307  
  1308  
  1309  
  1310  
  1311  
  1312  func putInlinedFunc(ctxt Context, s *FnState, callIdx int) error {
  1313  	ic := s.InlCalls.Calls[callIdx]
  1314  	callee := ic.AbsFunSym
  1315  
  1316  	abbrev := DW_ABRV_INLINED_SUBROUTINE_RANGES
  1317  	if len(ic.Ranges) == 1 {
  1318  		abbrev = DW_ABRV_INLINED_SUBROUTINE
  1319  	}
  1320  	Uleb128put(ctxt, s.Info, int64(abbrev))
  1321  
  1322  	if logDwarf {
  1323  		ctxt.Logf("putInlinedFunc(callee=%v,abbrev=%d)\n", callee, abbrev)
  1324  	}
  1325  
  1326  	
  1327  	putattr(ctxt, s.Info, abbrev, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, callee)
  1328  
  1329  	if abbrev == DW_ABRV_INLINED_SUBROUTINE_RANGES {
  1330  		putattr(ctxt, s.Info, abbrev, DW_FORM_sec_offset, DW_CLS_PTR, s.Ranges.Length(ctxt), s.Ranges)
  1331  		s.PutRanges(ctxt, ic.Ranges)
  1332  	} else {
  1333  		st := ic.Ranges[0].Start
  1334  		en := ic.Ranges[0].End
  1335  		putattr(ctxt, s.Info, abbrev, DW_FORM_addr, DW_CLS_ADDRESS, st, s.StartPC)
  1336  		putattr(ctxt, s.Info, abbrev, DW_FORM_addr, DW_CLS_ADDRESS, en, s.StartPC)
  1337  	}
  1338  
  1339  	
  1340  	ctxt.AddFileRef(s.Info, ic.CallFile)
  1341  	form := int(expandPseudoForm(DW_FORM_udata_pseudo))
  1342  	putattr(ctxt, s.Info, abbrev, form, DW_CLS_CONSTANT, int64(ic.CallLine), nil)
  1343  
  1344  	
  1345  	vars := ic.InlVars
  1346  	sort.Sort(byChildIndex(vars))
  1347  	inlIndex := ic.InlIndex
  1348  	var encbuf [20]byte
  1349  	for _, v := range vars {
  1350  		if !v.IsInAbstract {
  1351  			continue
  1352  		}
  1353  		putvar(ctxt, s, v, callee, abbrev, inlIndex, encbuf[:0])
  1354  	}
  1355  
  1356  	
  1357  	for _, sib := range inlChildren(callIdx, &s.InlCalls) {
  1358  		err := putInlinedFunc(ctxt, s, sib)
  1359  		if err != nil {
  1360  			return err
  1361  		}
  1362  	}
  1363  
  1364  	Uleb128put(ctxt, s.Info, 0)
  1365  	return nil
  1366  }
  1367  
  1368  
  1369  
  1370  
  1371  
  1372  
  1373  
  1374  
  1375  func PutConcreteFunc(ctxt Context, s *FnState, isWrapper bool) error {
  1376  	if logDwarf {
  1377  		ctxt.Logf("PutConcreteFunc(%v)\n", s.Info)
  1378  	}
  1379  	abbrev := DW_ABRV_FUNCTION_CONCRETE
  1380  	if isWrapper {
  1381  		abbrev = DW_ABRV_WRAPPER_CONCRETE
  1382  	}
  1383  	Uleb128put(ctxt, s.Info, int64(abbrev))
  1384  
  1385  	
  1386  	putattr(ctxt, s.Info, abbrev, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, s.Absfn)
  1387  
  1388  	
  1389  	putattr(ctxt, s.Info, abbrev, DW_FORM_addr, DW_CLS_ADDRESS, 0, s.StartPC)
  1390  	putattr(ctxt, s.Info, abbrev, DW_FORM_addr, DW_CLS_ADDRESS, s.Size, s.StartPC)
  1391  
  1392  	
  1393  	putattr(ctxt, s.Info, abbrev, DW_FORM_block1, DW_CLS_BLOCK, 1, []byte{DW_OP_call_frame_cfa})
  1394  
  1395  	if isWrapper {
  1396  		putattr(ctxt, s.Info, abbrev, DW_FORM_flag, DW_CLS_FLAG, int64(1), 0)
  1397  	}
  1398  
  1399  	
  1400  	if err := putPrunedScopes(ctxt, s, abbrev); err != nil {
  1401  		return err
  1402  	}
  1403  
  1404  	
  1405  	for _, sib := range inlChildren(-1, &s.InlCalls) {
  1406  		err := putInlinedFunc(ctxt, s, sib)
  1407  		if err != nil {
  1408  			return err
  1409  		}
  1410  	}
  1411  
  1412  	Uleb128put(ctxt, s.Info, 0)
  1413  	return nil
  1414  }
  1415  
  1416  
  1417  
  1418  
  1419  
  1420  
  1421  func PutDefaultFunc(ctxt Context, s *FnState, isWrapper bool) error {
  1422  	if logDwarf {
  1423  		ctxt.Logf("PutDefaultFunc(%v)\n", s.Info)
  1424  	}
  1425  	abbrev := DW_ABRV_FUNCTION
  1426  	if isWrapper {
  1427  		abbrev = DW_ABRV_WRAPPER
  1428  	}
  1429  	Uleb128put(ctxt, s.Info, int64(abbrev))
  1430  
  1431  	
  1432  	name := s.Name
  1433  	if s.Importpath != "" {
  1434  		name = strings.Replace(name, "\"\".", objabi.PathToPrefix(s.Importpath)+".", -1)
  1435  	}
  1436  
  1437  	putattr(ctxt, s.Info, DW_ABRV_FUNCTION, DW_FORM_string, DW_CLS_STRING, int64(len(name)), name)
  1438  	putattr(ctxt, s.Info, abbrev, DW_FORM_addr, DW_CLS_ADDRESS, 0, s.StartPC)
  1439  	putattr(ctxt, s.Info, abbrev, DW_FORM_addr, DW_CLS_ADDRESS, s.Size, s.StartPC)
  1440  	putattr(ctxt, s.Info, abbrev, DW_FORM_block1, DW_CLS_BLOCK, 1, []byte{DW_OP_call_frame_cfa})
  1441  	if isWrapper {
  1442  		putattr(ctxt, s.Info, abbrev, DW_FORM_flag, DW_CLS_FLAG, int64(1), 0)
  1443  	} else {
  1444  		ctxt.AddFileRef(s.Info, s.Filesym)
  1445  		putattr(ctxt, s.Info, abbrev, DW_FORM_udata, DW_CLS_CONSTANT, int64(s.StartLine), nil)
  1446  
  1447  		var ev int64
  1448  		if s.External {
  1449  			ev = 1
  1450  		}
  1451  		putattr(ctxt, s.Info, abbrev, DW_FORM_flag, DW_CLS_FLAG, ev, 0)
  1452  	}
  1453  
  1454  	
  1455  	if err := putPrunedScopes(ctxt, s, abbrev); err != nil {
  1456  		return err
  1457  	}
  1458  
  1459  	
  1460  	for _, sib := range inlChildren(-1, &s.InlCalls) {
  1461  		err := putInlinedFunc(ctxt, s, sib)
  1462  		if err != nil {
  1463  			return err
  1464  		}
  1465  	}
  1466  
  1467  	Uleb128put(ctxt, s.Info, 0)
  1468  	return nil
  1469  }
  1470  
  1471  
  1472  func putparamtypes(ctxt Context, s *FnState, scopes []Scope, fnabbrev int) []int64 {
  1473  	if fnabbrev == DW_ABRV_FUNCTION_CONCRETE {
  1474  		return nil
  1475  	}
  1476  
  1477  	maxDictIndex := uint16(0)
  1478  
  1479  	for i := range scopes {
  1480  		for _, v := range scopes[i].Vars {
  1481  			if v.DictIndex > maxDictIndex {
  1482  				maxDictIndex = v.DictIndex
  1483  			}
  1484  		}
  1485  	}
  1486  
  1487  	if maxDictIndex == 0 {
  1488  		return nil
  1489  	}
  1490  
  1491  	dictIndexToOffset := make([]int64, maxDictIndex)
  1492  
  1493  	for i := range scopes {
  1494  		for _, v := range scopes[i].Vars {
  1495  			if v.DictIndex == 0 || dictIndexToOffset[v.DictIndex-1] != 0 {
  1496  				continue
  1497  			}
  1498  
  1499  			dictIndexToOffset[v.DictIndex-1] = ctxt.CurrentOffset(s.Info)
  1500  
  1501  			Uleb128put(ctxt, s.Info, int64(DW_ABRV_DICT_INDEX))
  1502  			n := fmt.Sprintf(".param%d", v.DictIndex-1)
  1503  			putattr(ctxt, s.Info, DW_ABRV_DICT_INDEX, DW_FORM_string, DW_CLS_STRING, int64(len(n)), n)
  1504  			putattr(ctxt, s.Info, DW_ABRV_DICT_INDEX, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, v.Type)
  1505  			putattr(ctxt, s.Info, DW_ABRV_DICT_INDEX, DW_FORM_udata, DW_CLS_CONSTANT, int64(v.DictIndex-1), nil)
  1506  		}
  1507  	}
  1508  
  1509  	return dictIndexToOffset
  1510  }
  1511  
  1512  func putscope(ctxt Context, s *FnState, scopes []Scope, curscope int32, fnabbrev int, encbuf []byte) int32 {
  1513  
  1514  	if logDwarf {
  1515  		ctxt.Logf("putscope(%v,%d): vars:", s.Info, curscope)
  1516  		for i, v := range scopes[curscope].Vars {
  1517  			ctxt.Logf(" %d:%d:%s", i, v.ChildIndex, v.Name)
  1518  		}
  1519  		ctxt.Logf("\n")
  1520  	}
  1521  
  1522  	for _, v := range scopes[curscope].Vars {
  1523  		putvar(ctxt, s, v, s.Absfn, fnabbrev, -1, encbuf)
  1524  	}
  1525  	this := curscope
  1526  	curscope++
  1527  	for curscope < int32(len(scopes)) {
  1528  		scope := scopes[curscope]
  1529  		if scope.Parent != this {
  1530  			return curscope
  1531  		}
  1532  
  1533  		if len(scopes[curscope].Vars) == 0 {
  1534  			curscope = putscope(ctxt, s, scopes, curscope, fnabbrev, encbuf)
  1535  			continue
  1536  		}
  1537  
  1538  		if len(scope.Ranges) == 1 {
  1539  			Uleb128put(ctxt, s.Info, DW_ABRV_LEXICAL_BLOCK_SIMPLE)
  1540  			putattr(ctxt, s.Info, DW_ABRV_LEXICAL_BLOCK_SIMPLE, DW_FORM_addr, DW_CLS_ADDRESS, scope.Ranges[0].Start, s.StartPC)
  1541  			putattr(ctxt, s.Info, DW_ABRV_LEXICAL_BLOCK_SIMPLE, DW_FORM_addr, DW_CLS_ADDRESS, scope.Ranges[0].End, s.StartPC)
  1542  		} else {
  1543  			Uleb128put(ctxt, s.Info, DW_ABRV_LEXICAL_BLOCK_RANGES)
  1544  			putattr(ctxt, s.Info, DW_ABRV_LEXICAL_BLOCK_RANGES, DW_FORM_sec_offset, DW_CLS_PTR, s.Ranges.Length(ctxt), s.Ranges)
  1545  
  1546  			s.PutRanges(ctxt, scope.Ranges)
  1547  		}
  1548  
  1549  		curscope = putscope(ctxt, s, scopes, curscope, fnabbrev, encbuf)
  1550  
  1551  		Uleb128put(ctxt, s.Info, 0)
  1552  	}
  1553  	return curscope
  1554  }
  1555  
  1556  
  1557  func concreteVarAbbrev(varAbbrev int) int {
  1558  	switch varAbbrev {
  1559  	case DW_ABRV_AUTO:
  1560  		return DW_ABRV_AUTO_CONCRETE
  1561  	case DW_ABRV_PARAM:
  1562  		return DW_ABRV_PARAM_CONCRETE
  1563  	case DW_ABRV_AUTO_LOCLIST:
  1564  		return DW_ABRV_AUTO_CONCRETE_LOCLIST
  1565  	case DW_ABRV_PARAM_LOCLIST:
  1566  		return DW_ABRV_PARAM_CONCRETE_LOCLIST
  1567  	default:
  1568  		panic("should never happen")
  1569  	}
  1570  }
  1571  
  1572  
  1573  func determineVarAbbrev(v *Var, fnabbrev int) (int, bool, bool) {
  1574  	abbrev := v.Abbrev
  1575  
  1576  	
  1577  	
  1578  	missing := false
  1579  	switch {
  1580  	case abbrev == DW_ABRV_AUTO_LOCLIST && v.PutLocationList == nil:
  1581  		missing = true
  1582  		abbrev = DW_ABRV_AUTO
  1583  	case abbrev == DW_ABRV_PARAM_LOCLIST && v.PutLocationList == nil:
  1584  		missing = true
  1585  		abbrev = DW_ABRV_PARAM
  1586  	}
  1587  
  1588  	
  1589  	concrete := true
  1590  	switch fnabbrev {
  1591  	case DW_ABRV_FUNCTION, DW_ABRV_WRAPPER:
  1592  		concrete = false
  1593  	case DW_ABRV_FUNCTION_CONCRETE, DW_ABRV_WRAPPER_CONCRETE:
  1594  		
  1595  		
  1596  		
  1597  		if !v.IsInAbstract {
  1598  			concrete = false
  1599  		}
  1600  	case DW_ABRV_INLINED_SUBROUTINE, DW_ABRV_INLINED_SUBROUTINE_RANGES:
  1601  	default:
  1602  		panic("should never happen")
  1603  	}
  1604  
  1605  	
  1606  	if concrete {
  1607  		abbrev = concreteVarAbbrev(abbrev)
  1608  	}
  1609  
  1610  	return abbrev, missing, concrete
  1611  }
  1612  
  1613  func abbrevUsesLoclist(abbrev int) bool {
  1614  	switch abbrev {
  1615  	case DW_ABRV_AUTO_LOCLIST, DW_ABRV_AUTO_CONCRETE_LOCLIST,
  1616  		DW_ABRV_PARAM_LOCLIST, DW_ABRV_PARAM_CONCRETE_LOCLIST:
  1617  		return true
  1618  	default:
  1619  		return false
  1620  	}
  1621  }
  1622  
  1623  
  1624  func putAbstractVar(ctxt Context, info Sym, v *Var) {
  1625  	
  1626  	abbrev := v.Abbrev
  1627  	switch abbrev {
  1628  	case DW_ABRV_AUTO, DW_ABRV_AUTO_LOCLIST:
  1629  		abbrev = DW_ABRV_AUTO_ABSTRACT
  1630  	case DW_ABRV_PARAM, DW_ABRV_PARAM_LOCLIST:
  1631  		abbrev = DW_ABRV_PARAM_ABSTRACT
  1632  	}
  1633  
  1634  	Uleb128put(ctxt, info, int64(abbrev))
  1635  	putattr(ctxt, info, abbrev, DW_FORM_string, DW_CLS_STRING, int64(len(v.Name)), v.Name)
  1636  
  1637  	
  1638  	if abbrev == DW_ABRV_PARAM_ABSTRACT {
  1639  		var isReturn int64
  1640  		if v.IsReturnValue {
  1641  			isReturn = 1
  1642  		}
  1643  		putattr(ctxt, info, abbrev, DW_FORM_flag, DW_CLS_FLAG, isReturn, nil)
  1644  	}
  1645  
  1646  	
  1647  	if abbrev != DW_ABRV_PARAM_ABSTRACT {
  1648  		
  1649  		putattr(ctxt, info, abbrev, DW_FORM_udata, DW_CLS_CONSTANT, int64(v.DeclLine), nil)
  1650  	}
  1651  
  1652  	
  1653  	putattr(ctxt, info, abbrev, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, v.Type)
  1654  
  1655  	
  1656  }
  1657  
  1658  func putvar(ctxt Context, s *FnState, v *Var, absfn Sym, fnabbrev, inlIndex int, encbuf []byte) {
  1659  	
  1660  	abbrev, missing, concrete := determineVarAbbrev(v, fnabbrev)
  1661  
  1662  	Uleb128put(ctxt, s.Info, int64(abbrev))
  1663  
  1664  	
  1665  	if concrete {
  1666  		
  1667  		
  1668  		
  1669  		
  1670  		putattr(ctxt, s.Info, abbrev, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, absfn)
  1671  		ctxt.RecordDclReference(s.Info, absfn, int(v.ChildIndex), inlIndex)
  1672  	} else {
  1673  		
  1674  		n := v.Name
  1675  		putattr(ctxt, s.Info, abbrev, DW_FORM_string, DW_CLS_STRING, int64(len(n)), n)
  1676  		if abbrev == DW_ABRV_PARAM || abbrev == DW_ABRV_PARAM_LOCLIST || abbrev == DW_ABRV_PARAM_ABSTRACT {
  1677  			var isReturn int64
  1678  			if v.IsReturnValue {
  1679  				isReturn = 1
  1680  			}
  1681  			putattr(ctxt, s.Info, abbrev, DW_FORM_flag, DW_CLS_FLAG, isReturn, nil)
  1682  		}
  1683  		putattr(ctxt, s.Info, abbrev, DW_FORM_udata, DW_CLS_CONSTANT, int64(v.DeclLine), nil)
  1684  		if v.DictIndex > 0 && s.dictIndexToOffset != nil && s.dictIndexToOffset[v.DictIndex-1] != 0 {
  1685  			
  1686  			putattr(ctxt, s.Info, abbrev, DW_FORM_ref_addr, DW_CLS_REFERENCE, s.dictIndexToOffset[v.DictIndex-1], s.Info)
  1687  		} else {
  1688  			putattr(ctxt, s.Info, abbrev, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, v.Type)
  1689  		}
  1690  	}
  1691  
  1692  	if abbrevUsesLoclist(abbrev) {
  1693  		putattr(ctxt, s.Info, abbrev, DW_FORM_sec_offset, DW_CLS_PTR, s.Loc.Length(ctxt), s.Loc)
  1694  		v.PutLocationList(s.Loc, s.StartPC)
  1695  	} else {
  1696  		loc := encbuf[:0]
  1697  		switch {
  1698  		case missing:
  1699  			break 
  1700  		case v.StackOffset == 0:
  1701  			loc = append(loc, DW_OP_call_frame_cfa)
  1702  		default:
  1703  			loc = append(loc, DW_OP_fbreg)
  1704  			loc = AppendSleb128(loc, int64(v.StackOffset))
  1705  		}
  1706  		putattr(ctxt, s.Info, abbrev, DW_FORM_block1, DW_CLS_BLOCK, int64(len(loc)), loc)
  1707  	}
  1708  
  1709  	
  1710  }
  1711  
  1712  
  1713  type byChildIndex []*Var
  1714  
  1715  func (s byChildIndex) Len() int           { return len(s) }
  1716  func (s byChildIndex) Less(i, j int) bool { return s[i].ChildIndex < s[j].ChildIndex }
  1717  func (s byChildIndex) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
  1718  
  1719  
  1720  
  1721  
  1722  
  1723  func IsDWARFEnabledOnAIXLd(extld []string) (bool, error) {
  1724  	name, args := extld[0], extld[1:]
  1725  	args = append(args, "-Wl,-V")
  1726  	out, err := exec.Command(name, args...).CombinedOutput()
  1727  	if err != nil {
  1728  		
  1729  		
  1730  		
  1731  		if !bytes.Contains(out, []byte("0711-317")) {
  1732  			return false, fmt.Errorf("%s -Wl,-V failed: %v\n%s", extld, err, out)
  1733  		}
  1734  	}
  1735  	
  1736  	
  1737  	
  1738  	out = bytes.TrimPrefix(out, []byte("/usr/bin/ld: LD "))
  1739  	vers := string(bytes.Split(out, []byte("("))[0])
  1740  	subvers := strings.Split(vers, ".")
  1741  	if len(subvers) != 3 {
  1742  		return false, fmt.Errorf("cannot parse %s -Wl,-V (%s): %v\n", extld, out, err)
  1743  	}
  1744  	if v, err := strconv.Atoi(subvers[0]); err != nil || v < 7 {
  1745  		return false, nil
  1746  	} else if v > 7 {
  1747  		return true, nil
  1748  	}
  1749  	if v, err := strconv.Atoi(subvers[1]); err != nil || v < 2 {
  1750  		return false, nil
  1751  	} else if v > 2 {
  1752  		return true, nil
  1753  	}
  1754  	if v, err := strconv.Atoi(subvers[2]); err != nil || v < 2 {
  1755  		return false, nil
  1756  	}
  1757  	return true, nil
  1758  }