github.com/Rookout/GoSDK@v0.1.48/pkg/services/collection/variable/types.go (about)

     1  // The MIT License (MIT)
     2  
     3  // Copyright (c) 2014 Derek Parker
     4  
     5  // Permission is hereby granted, free of charge, to any person obtaining a copy of
     6  // this software and associated documentation files (the "Software"), to deal in
     7  // the Software without restriction, including without limitation the rights to
     8  // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
     9  // the Software, and to permit persons to whom the Software is furnished to do so,
    10  // subject to the following conditions:
    11  
    12  // The above copyright notice and this permission notice shall be included in all
    13  // copies or substantial portions of the Software.
    14  
    15  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    16  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
    17  // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
    18  // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
    19  // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
    20  // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    21  
    22  package variable
    23  
    24  import (
    25  	"bytes"
    26  	"errors"
    27  	"fmt"
    28  	"go/constant"
    29  	"reflect"
    30  	"strings"
    31  	"unsafe"
    32  
    33  	"github.com/Rookout/GoSDK/pkg/config"
    34  	"github.com/Rookout/GoSDK/pkg/services/collection/memory"
    35  	"github.com/Rookout/GoSDK/pkg/services/instrumentation/binary_info"
    36  	"github.com/Rookout/GoSDK/pkg/services/instrumentation/dwarf/godwarf"
    37  	"github.com/Rookout/GoSDK/pkg/services/instrumentation/module"
    38  )
    39  
    40  
    41  
    42  
    43  
    44  
    45  
    46  
    47  
    48  
    49  func runtimeTypeToDIE(_type *Variable, dataAddr uint64) (typ godwarf.Type, kind int64, err error) {
    50  	bi := _type.bi
    51  
    52  	_type = _type.MaybeDereference()
    53  
    54  	// go 1.11 implementation: use extended attribute in debug_info
    55  
    56  	md := module.FindModuleDataForType(_type.Addr)
    57  	if md != nil {
    58  		so := imageOfPC(bi, md.GetFirstPC())
    59  		if so != nil {
    60  			if rtdie, ok := so.RuntimeTypeToDIE[_type.Addr-md.GetTypesAddr()]; ok {
    61  				typ, err := godwarf.ReadType(so.Dwarf, so.Index, rtdie.Offset, &so.TypeCache)
    62  				if err != nil {
    63  					return nil, 0, fmt.Errorf("invalid interface type: %v", err)
    64  				}
    65  				if rtdie.Kind == -1 {
    66  					kindField := _type.loadFieldNamed("kind")
    67  					if kindField == nil || kindField.Value == nil {
    68  						kindField = _type.loadFieldNamed("Kind_")
    69  						if kindField == nil || kindField.Value == nil {
    70  							return typ, rtdie.Kind, nil
    71  						}
    72  					}
    73  					rtdie.Kind, _ = constant.Int64Val(kindField.Value)
    74  				}
    75  				return typ, rtdie.Kind, nil
    76  			}
    77  		}
    78  	}
    79  
    80  	// go1.7 to go1.10 implementation: convert runtime._type structs to type names
    81  
    82  	if binary_info.GoVersionAfterOrEqual(1, 17) {
    83  		
    84  		
    85  		
    86  		
    87  		
    88  		return nil, 0, fmt.Errorf("could not resolve interface type")
    89  	}
    90  
    91  	typename, kind, err := nameOfRuntimeType(_type)
    92  	if err != nil {
    93  		return nil, 0, fmt.Errorf("invalid interface type: %v", err)
    94  	}
    95  
    96  	typ, err = bi.FindType(typename)
    97  	if err != nil {
    98  		return nil, 0, fmt.Errorf("interface type %q not found for %#x: %v", typename, dataAddr, err)
    99  	}
   100  
   101  	return typ, kind, nil
   102  }
   103  
   104  
   105  func imageOfPC(bi *binary_info.BinaryInfo, pc uint64) *binary_info.Image {
   106  	fn := bi.PCToFunc(pc)
   107  	if fn != nil {
   108  		return bi.FuncToImage(fn)
   109  	}
   110  
   111  	
   112  	var so *binary_info.Image
   113  	for i := range bi.Images {
   114  		if int64(bi.Images[i].StaticBase) > int64(pc) {
   115  			continue
   116  		}
   117  		if so == nil || int64(bi.Images[i].StaticBase) > int64(so.StaticBase) {
   118  			so = bi.Images[i]
   119  		}
   120  	}
   121  	return so
   122  }
   123  
   124  
   125  
   126  const (
   127  	tflagUncommon  = 1 << 0
   128  	tflagExtraStar = 1 << 1
   129  	tflagNamed     = 1 << 2
   130  )
   131  
   132  
   133  
   134  
   135  func nameOfRuntimeType(_type *Variable) (typename string, kind int64, err error) {
   136  	if e, ok := _type.bi.NameOfRuntimeType[_type.Addr]; ok {
   137  		return e.Typename, e.Kind, nil
   138  	}
   139  
   140  	var tflag int64
   141  
   142  	if tflagField := _type.loadFieldNamed("tflag"); tflagField != nil && tflagField.Value != nil {
   143  		tflag, _ = constant.Int64Val(tflagField.Value)
   144  	}
   145  	if kindField := _type.loadFieldNamed("kind"); kindField != nil && kindField.Value != nil {
   146  		kind, _ = constant.Int64Val(kindField.Value)
   147  	}
   148  
   149  	
   150  	
   151  	if tflag&tflagNamed != 0 {
   152  		typename, err = nameOfNamedRuntimeType(_type, kind, tflag)
   153  		if err == nil {
   154  			_type.bi.NameOfRuntimeType[_type.Addr] = binary_info.NameOfRuntimeTypeEntry{Typename: typename, Kind: kind}
   155  		}
   156  		return typename, kind, err
   157  	}
   158  
   159  	typename, err = nameOfUnnamedRuntimeType(_type, kind, tflag)
   160  	if err == nil {
   161  		_type.bi.NameOfRuntimeType[_type.Addr] = binary_info.NameOfRuntimeTypeEntry{Typename: typename, Kind: kind}
   162  	}
   163  	return typename, kind, err
   164  }
   165  
   166  func fieldToType(_type *Variable, fieldName string) (string, error) {
   167  	typeField, err := _type.structMember(fieldName)
   168  	if err != nil {
   169  		return "", err
   170  	}
   171  	typeField = typeField.MaybeDereference()
   172  	typename, _, err := nameOfRuntimeType(typeField)
   173  	return typename, err
   174  }
   175  
   176  func nameOfUnnamedRuntimeType(_type *Variable, kind, tflag int64) (string, error) {
   177  	_type, err := specificRuntimeType(_type, kind)
   178  	if err != nil {
   179  		return "", err
   180  	}
   181  
   182  	
   183  	switch reflect.Kind(kind & kindMask) {
   184  	case reflect.Array:
   185  		var len int64
   186  		if lenField := _type.loadFieldNamed("len"); lenField != nil && lenField.Value != nil {
   187  			len, _ = constant.Int64Val(lenField.Value)
   188  		}
   189  		elemname, err := fieldToType(_type, "elem")
   190  		if err != nil {
   191  			return "", err
   192  		}
   193  		return fmt.Sprintf("[%d]%s", len, elemname), nil
   194  	case reflect.Chan:
   195  		elemname, err := fieldToType(_type, "elem")
   196  		if err != nil {
   197  			return "", err
   198  		}
   199  		return "chan " + elemname, nil
   200  	case reflect.Func:
   201  		return nameOfFuncRuntimeType(_type, tflag, true)
   202  	case reflect.Interface:
   203  		return nameOfInterfaceRuntimeType(_type, kind, tflag)
   204  	case reflect.Map:
   205  		keyname, err := fieldToType(_type, "key")
   206  		if err != nil {
   207  			return "", err
   208  		}
   209  		elemname, err := fieldToType(_type, "elem")
   210  		if err != nil {
   211  			return "", err
   212  		}
   213  		return "map[" + keyname + "]" + elemname, nil
   214  	case reflect.Ptr:
   215  		elemname, err := fieldToType(_type, "elem")
   216  		if err != nil {
   217  			return "", err
   218  		}
   219  		return "*" + elemname, nil
   220  	case reflect.Slice:
   221  		elemname, err := fieldToType(_type, "elem")
   222  		if err != nil {
   223  			return "", err
   224  		}
   225  		return "[]" + elemname, nil
   226  	case reflect.Struct:
   227  		return nameOfStructRuntimeType(_type, kind, tflag)
   228  	default:
   229  		return nameOfNamedRuntimeType(_type, kind, tflag)
   230  	}
   231  }
   232  
   233  
   234  
   235  
   236  
   237  func nameOfFuncRuntimeType(_type *Variable, tflag int64, anonymous bool) (string, error) {
   238  	rtyp, err := _type.bi.FindType(_type.bi.RuntimeTypeTypename())
   239  	if err != nil {
   240  		return "", err
   241  	}
   242  	prtyp := pointerTo(rtyp, _type.bi)
   243  
   244  	uadd := _type.RealType.Common().ByteSize
   245  	if ut := uncommon(_type, tflag); ut != nil {
   246  		uadd += ut.RealType.Common().ByteSize
   247  	}
   248  
   249  	var inCount, outCount int64
   250  	if inCountField := _type.loadFieldNamed("inCount"); inCountField != nil && inCountField.Value != nil {
   251  		inCount, _ = constant.Int64Val(inCountField.Value)
   252  	}
   253  	if outCountField := _type.loadFieldNamed("outCount"); outCountField != nil && outCountField.Value != nil {
   254  		outCount, _ = constant.Int64Val(outCountField.Value)
   255  		
   256  		outCount = outCount & (1<<15 - 1)
   257  	}
   258  
   259  	cursortyp := _type.spawn("", _type.Addr+uint64(uadd), prtyp, _type.Mem)
   260  	var buf bytes.Buffer
   261  	if anonymous {
   262  		buf.WriteString("func(")
   263  	} else {
   264  		buf.WriteString("(")
   265  	}
   266  
   267  	for i := int64(0); i < inCount; i++ {
   268  		argtype := cursortyp.MaybeDereference()
   269  		cursortyp.Addr += uint64(_type.bi.PointerSize)
   270  		argtypename, _, err := nameOfRuntimeType(argtype)
   271  		if err != nil {
   272  			return "", err
   273  		}
   274  		buf.WriteString(argtypename)
   275  		if i != inCount-1 {
   276  			buf.WriteString(", ")
   277  		}
   278  	}
   279  	buf.WriteString(")")
   280  
   281  	switch outCount {
   282  	case 0:
   283  		
   284  	case 1:
   285  		buf.WriteString(" ")
   286  		argtype := cursortyp.MaybeDereference()
   287  		argtypename, _, err := nameOfRuntimeType(argtype)
   288  		if err != nil {
   289  			return "", err
   290  		}
   291  		buf.WriteString(argtypename)
   292  	default:
   293  		buf.WriteString(" (")
   294  		for i := int64(0); i < outCount; i++ {
   295  			argtype := cursortyp.MaybeDereference()
   296  			cursortyp.Addr += uint64(_type.bi.PointerSize)
   297  			argtypename, _, err := nameOfRuntimeType(argtype)
   298  			if err != nil {
   299  				return "", err
   300  			}
   301  			buf.WriteString(argtypename)
   302  			if i != inCount-1 {
   303  				buf.WriteString(", ")
   304  			}
   305  		}
   306  		buf.WriteString(")")
   307  	}
   308  	return buf.String(), nil
   309  }
   310  
   311  
   312  
   313  
   314  
   315  const (
   316  	imethodFieldName       = "name"
   317  	imethodFieldItyp       = "ityp"
   318  	interfacetypeFieldMhdr = "mhdr"
   319  )
   320  
   321  func resolveTypeOff(bi *binary_info.BinaryInfo, typeAddr, off uint64, mem memory.MemoryReader) (*Variable, error) {
   322  	
   323  	md := module.FindModuleDataForType(typeAddr)
   324  
   325  	rtyp, err := bi.FindType(bi.RuntimeTypeTypename())
   326  	if err != nil {
   327  		return nil, err
   328  	}
   329  
   330  	if md == nil {
   331  		v, err := reflectOffsMapAccess(bi, off, mem)
   332  		if err != nil {
   333  			return nil, err
   334  		}
   335  		v.LoadValue()
   336  		addr, _ := constant.Int64Val(v.Value)
   337  		return v.spawn(v.Name, uint64(addr), rtyp, mem), nil
   338  	}
   339  
   340  	if t, ok := md.GetTypeMap()[module.TypeOff(off)]; ok {
   341  		tVar := NewVariable("", uint64(t), nil, mem, bi, config.GetDefaultDumpConfig(), 0, &VariablesCache{})
   342  		tVar.Value = constant.MakeUint64(uint64(t))
   343  		return tVar, nil
   344  	}
   345  
   346  	res := md.GetTypesAddr() + off
   347  
   348  	return NewVariable("", uint64(res), rtyp, mem, bi, config.GetDefaultDumpConfig(), 0, &VariablesCache{}), nil
   349  }
   350  
   351  func nameOfInterfaceRuntimeType(_type *Variable, kind, tflag int64) (string, error) {
   352  	var buf bytes.Buffer
   353  	buf.WriteString("interface {")
   354  
   355  	methods, _ := _type.structMember(interfacetypeFieldMhdr)
   356  	methods.loadArrayValues(0)
   357  	if methods.Unreadable != nil {
   358  		return "", nil
   359  	}
   360  
   361  	if len(methods.Children) == 0 {
   362  		buf.WriteString("}")
   363  		return buf.String(), nil
   364  	}
   365  	buf.WriteString(" ")
   366  
   367  	for i, im := range methods.Children {
   368  		var methodname, methodtype string
   369  		for i := range im.Children {
   370  			switch im.Children[i].Name {
   371  			case imethodFieldName:
   372  				nameoff, _ := constant.Int64Val(im.Children[i].Value)
   373  				var err error
   374  				methodname, _, _, err = resolveNameOff(_type.bi, _type.Addr, uint64(nameoff), _type.Mem)
   375  				if err != nil {
   376  					return "", err
   377  				}
   378  
   379  			case imethodFieldItyp:
   380  				typeoff, _ := constant.Int64Val(im.Children[i].Value)
   381  				typ, err := resolveTypeOff(_type.bi, _type.Addr, uint64(typeoff), _type.Mem)
   382  				if err != nil {
   383  					return "", err
   384  				}
   385  				typ, err = specificRuntimeType(typ, int64(reflect.Func))
   386  				if err != nil {
   387  					return "", err
   388  				}
   389  				var tflag int64
   390  				if tflagField := typ.loadFieldNamed("tflag"); tflagField != nil && tflagField.Value != nil {
   391  					tflag, _ = constant.Int64Val(tflagField.Value)
   392  				}
   393  				methodtype, err = nameOfFuncRuntimeType(typ, tflag, false)
   394  				if err != nil {
   395  					return "", err
   396  				}
   397  			}
   398  		}
   399  
   400  		buf.WriteString(methodname)
   401  		buf.WriteString(methodtype)
   402  
   403  		if i != len(methods.Children)-1 {
   404  			buf.WriteString("; ")
   405  		} else {
   406  			buf.WriteString(" }")
   407  		}
   408  	}
   409  	return buf.String(), nil
   410  }
   411  
   412  func nameOfStructRuntimeType(_type *Variable, kind, tflag int64) (string, error) {
   413  	var buf bytes.Buffer
   414  	buf.WriteString("struct {")
   415  
   416  	fields, _ := _type.structMember("fields")
   417  	fields.loadArrayValues(0)
   418  	if fields.Unreadable != nil {
   419  		return "", fields.Unreadable
   420  	}
   421  
   422  	if len(fields.Children) == 0 {
   423  		buf.WriteString("}")
   424  		return buf.String(), nil
   425  	}
   426  	buf.WriteString(" ")
   427  
   428  	for i, field := range fields.Children {
   429  		var fieldname, fieldtypename string
   430  		var typeField *Variable
   431  		isembed := false
   432  		for i := range field.Children {
   433  			switch field.Children[i].Name {
   434  			case "name":
   435  				var nameoff int64
   436  				switch field.Children[i].Kind {
   437  				case reflect.Struct:
   438  					nameoff = int64(field.Children[i].fieldVariable("bytes").Children[0].Addr)
   439  				default:
   440  					nameoff, _ = constant.Int64Val(field.Children[i].Value)
   441  				}
   442  
   443  				var err error
   444  				fieldname, _, _, err = loadName(uint64(nameoff), _type.Mem)
   445  				if err != nil {
   446  					return "", err
   447  				}
   448  
   449  			case "typ":
   450  				typeField = field.Children[i].MaybeDereference()
   451  				var err error
   452  				fieldtypename, _, err = nameOfRuntimeType(typeField)
   453  				if err != nil {
   454  					return "", err
   455  				}
   456  
   457  			case "offsetAnon":
   458  				
   459  				
   460  				
   461  				
   462  				
   463  				
   464  				
   465  				offsetAnon, _ := constant.Int64Val(field.Children[i].Value)
   466  				isembed = offsetAnon%2 != 0
   467  			}
   468  		}
   469  
   470  		
   471  		if fieldname != "" && !isembed {
   472  			buf.WriteString(fieldname)
   473  			buf.WriteString(" ")
   474  		}
   475  		buf.WriteString(fieldtypename)
   476  		if i != len(fields.Children)-1 {
   477  			buf.WriteString("; ")
   478  		} else {
   479  			buf.WriteString(" }")
   480  		}
   481  	}
   482  
   483  	return buf.String(), nil
   484  }
   485  
   486  
   487  
   488  
   489  
   490  
   491  
   492  
   493  
   494  
   495  
   496  
   497  
   498  
   499  
   500  
   501  
   502  func nameOfNamedRuntimeType(_type *Variable, kind, tflag int64) (typename string, err error) {
   503  	var strOff int64
   504  	if strField := _type.loadFieldNamed("str"); strField != nil && strField.Value != nil {
   505  		strOff, _ = constant.Int64Val(strField.Value)
   506  	} else {
   507  		return "", errors.New("could not find str field")
   508  	}
   509  
   510  	
   511  	
   512  	
   513  
   514  	typename, _, _, err = resolveNameOff(_type.bi, _type.Addr, uint64(strOff), _type.Mem)
   515  	if err != nil {
   516  		return "", err
   517  	}
   518  
   519  	if tflag&tflagExtraStar != 0 {
   520  		typename = typename[1:]
   521  	}
   522  
   523  	if i := strings.Index(typename, "."); i >= 0 {
   524  		typename = typename[i+1:]
   525  	} else {
   526  		return typename, nil
   527  	}
   528  
   529  	
   530  	
   531  
   532  	_type, err = specificRuntimeType(_type, kind)
   533  	if err != nil {
   534  		return "", err
   535  	}
   536  
   537  	if ut := uncommon(_type, tflag); ut != nil {
   538  		if pkgPathField := ut.loadFieldNamed("pkgpath"); pkgPathField != nil && pkgPathField.Value != nil {
   539  			pkgPathOff, _ := constant.Int64Val(pkgPathField.Value)
   540  			pkgPath, _, _, err := resolveNameOff(_type.bi, _type.Addr, uint64(pkgPathOff), _type.Mem)
   541  			if err != nil {
   542  				return "", err
   543  			}
   544  			if slash := strings.LastIndex(pkgPath, "/"); slash >= 0 {
   545  				fixedName := strings.Replace(pkgPath[slash+1:], ".", "%2e", -1)
   546  				if fixedName != pkgPath[slash+1:] {
   547  					pkgPath = pkgPath[:slash+1] + fixedName
   548  				}
   549  			}
   550  			typename = pkgPath + "." + typename
   551  		}
   552  	}
   553  
   554  	return typename, nil
   555  }
   556  
   557  func specificRuntimeType(_type *Variable, kind int64) (*Variable, error) {
   558  	typ, err := typeForKind(kind, _type.bi)
   559  	if err != nil {
   560  		return nil, err
   561  	}
   562  	if typ == nil {
   563  		return _type, nil
   564  	}
   565  
   566  	return _type.spawn(_type.Name, _type.Addr, typ, _type.Mem), nil
   567  }
   568  
   569  var kindToRuntimeTypeName = map[reflect.Kind]string{
   570  	reflect.Array:     "runtime.arraytype",
   571  	reflect.Chan:      "runtime.chantype",
   572  	reflect.Func:      "runtime.functype",
   573  	reflect.Interface: "runtime.interfacetype",
   574  	reflect.Map:       "runtime.maptype",
   575  	reflect.Ptr:       "runtime.ptrtype",
   576  	reflect.Slice:     "runtime.slicetype",
   577  	reflect.Struct:    "runtime.structtype",
   578  }
   579  
   580  
   581  
   582  
   583  func typeForKind(kind int64, bi *binary_info.BinaryInfo) (*godwarf.StructType, error) {
   584  	typename, ok := kindToRuntimeTypeName[reflect.Kind(kind&kindMask)]
   585  	if !ok {
   586  		return nil, nil
   587  	}
   588  	typ, err := bi.FindType(typename)
   589  	if err != nil {
   590  		return nil, err
   591  	}
   592  	typ = resolveTypedef(typ)
   593  	return typ.(*godwarf.StructType), nil
   594  }
   595  
   596  
   597  func uncommon(_type *Variable, tflag int64) *Variable {
   598  	if tflag&tflagUncommon == 0 {
   599  		return nil
   600  	}
   601  
   602  	typ, err := _type.bi.FindType("runtime.uncommontype")
   603  	if err != nil {
   604  		return nil
   605  	}
   606  
   607  	return _type.spawn(_type.Name, _type.Addr+uint64(_type.RealType.Size()), typ, _type.Mem)
   608  }
   609  
   610  func resolveNameOff(bi *binary_info.BinaryInfo, typeAddr, off uint64, mem memory.MemoryReader) (name, tag string, pkgpathoff int32, err error) {
   611  	
   612  	if md := module.FindModuleDataForType(typeAddr); md != nil {
   613  		return loadName(md.GetTypesAddr()+off, mem)
   614  	}
   615  
   616  	v, err := reflectOffsMapAccess(bi, off, mem)
   617  	if err != nil {
   618  		return "", "", 0, err
   619  	}
   620  
   621  	resv := v.MaybeDereference()
   622  	if resv.Unreadable != nil {
   623  		return "", "", 0, resv.Unreadable
   624  	}
   625  
   626  	return loadName(resv.Addr, mem)
   627  }
   628  
   629  func reflectOffsMapAccess(bi *binary_info.BinaryInfo, off uint64, mem memory.MemoryReader) (*Variable, error) {
   630  	v := NewVariable("", 0, nil, mem, bi, config.GetDefaultDumpConfig(), 0, &VariablesCache{})
   631  	v.Value = constant.MakeUint64(uint64(uintptr(reflectOffs.m[int32(off)])))
   632  	v.Addr = uint64(uintptr(reflectOffs.m[int32(off)]))
   633  	return v, nil
   634  }
   635  
   636  type lockRankStruct struct {
   637  }
   638  
   639  
   640  
   641  
   642  
   643  
   644  type mutex struct {
   645  	
   646  	lockRankStruct
   647  	
   648  	
   649  	
   650  	key uintptr
   651  }
   652  
   653  //go:linkname reflectOffs runtime.reflectOffs
   654  var reflectOffs struct {
   655  	lock mutex
   656  	next int32
   657  	m    map[int32]unsafe.Pointer
   658  	minv map[unsafe.Pointer]int32
   659  }
   660  
   661  const (
   662  	
   663  	nameflagExported = 1 << 0
   664  	nameflagHasTag   = 1 << 1
   665  	nameflagHasPkg   = 1 << 2
   666  )
   667  
   668  func loadName(addr uint64, mem memory.MemoryReader) (name, tag string, pkgpathoff int32, err error) {
   669  	off := addr
   670  	namedata := make([]byte, 3)
   671  	_, err = mem.ReadMemory(namedata, off)
   672  	off += 3
   673  	if err != nil {
   674  		return "", "", 0, err
   675  	}
   676  
   677  	namelen := uint16(namedata[1])<<8 | uint16(namedata[2])
   678  
   679  	rawstr := make([]byte, int(namelen))
   680  	_, err = mem.ReadMemory(rawstr, off)
   681  	off += uint64(namelen)
   682  	if err != nil {
   683  		return "", "", 0, err
   684  	}
   685  
   686  	name = string(rawstr)
   687  
   688  	if namedata[0]&nameflagHasTag != 0 {
   689  		taglendata := make([]byte, 2)
   690  		_, err = mem.ReadMemory(taglendata, off)
   691  		off += 2
   692  		if err != nil {
   693  			return "", "", 0, err
   694  		}
   695  		taglen := uint16(taglendata[0])<<8 | uint16(taglendata[1])
   696  
   697  		rawstr := make([]byte, int(taglen))
   698  		_, err = mem.ReadMemory(rawstr, off)
   699  		off += uint64(taglen)
   700  		if err != nil {
   701  			return "", "", 0, err
   702  		}
   703  
   704  		tag = string(rawstr)
   705  	}
   706  
   707  	if namedata[0]&nameflagHasPkg != 0 {
   708  		pkgdata := make([]byte, 4)
   709  		_, err = mem.ReadMemory(pkgdata, off)
   710  		if err != nil {
   711  			return "", "", 0, err
   712  		}
   713  
   714  		
   715  		copy((*[4]byte)(unsafe.Pointer(&pkgpathoff))[:], pkgdata)
   716  	}
   717  
   718  	return name, tag, pkgpathoff, nil
   719  }
   720  
   721  
   722  
   723  func resolveParametricType(bi *binary_info.BinaryInfo, mem memory.MemoryReader, t godwarf.Type, dictAddr uint64) (godwarf.Type, error) {
   724  	ptyp, _ := t.(*godwarf.ParametricType)
   725  	if ptyp == nil {
   726  		return t, nil
   727  	}
   728  	if dictAddr == 0 {
   729  		return ptyp.TypedefType.Type, errors.New("parametric type without a dictionary")
   730  	}
   731  	rtypeAddr, err := readUintRaw(mem, dictAddr+uint64(ptyp.DictIndex*int64(bi.PointerSize)), int64(bi.PointerSize))
   732  	if err != nil {
   733  		return ptyp.TypedefType.Type, err
   734  	}
   735  	runtimeType, err := bi.FindType(bi.RuntimeTypeTypename())
   736  	if err != nil {
   737  		return ptyp.TypedefType.Type, err
   738  	}
   739  	_type := NewVariable("", rtypeAddr, runtimeType, mem, bi, config.GetDefaultDumpConfig(), dictAddr, &VariablesCache{})
   740  
   741  	typ, _, err := runtimeTypeToDIE(_type, 0)
   742  	if err != nil {
   743  		return ptyp.TypedefType.Type, err
   744  	}
   745  
   746  	return typ, nil
   747  }