github.com/Rookout/GoSDK@v0.1.48/pkg/services/collection/variable/variable.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  	"encoding/binary"
    27  	"errors"
    28  	"fmt"
    29  	"go/constant"
    30  	"go/token"
    31  	"math"
    32  	"reflect"
    33  	"strconv"
    34  	"strings"
    35  	"time"
    36  	"unsafe"
    37  
    38  	"github.com/Rookout/GoSDK/pkg/config"
    39  	"github.com/Rookout/GoSDK/pkg/logger"
    40  	"github.com/Rookout/GoSDK/pkg/rookoutErrors"
    41  	"github.com/Rookout/GoSDK/pkg/services/collection/memory"
    42  	"github.com/Rookout/GoSDK/pkg/services/instrumentation/binary_info"
    43  	"github.com/Rookout/GoSDK/pkg/services/instrumentation/dwarf/godwarf"
    44  	"github.com/Rookout/GoSDK/pkg/services/instrumentation/dwarf/op"
    45  )
    46  
    47  
    48  
    49  
    50  const (
    51  	kindDirectIface = 1 << 5
    52  	kindGCProg      = 1 << 6 
    53  	kindNoPointers  = 1 << 7
    54  	kindMask        = (1 << 5) - 1
    55  )
    56  
    57  type variableFlags uint16
    58  
    59  const (
    60  	
    61  	
    62  	
    63  	
    64  	
    65  	
    66  	VariableEscaped variableFlags = 1 << iota
    67  	
    68  	
    69  	VariableShadowed
    70  	
    71  	VariableConstant
    72  	
    73  	VariableArgument
    74  	
    75  	VariableReturnArgument
    76  	
    77  	
    78  	
    79  	
    80  	
    81  	VariableFakeAddress
    82  	
    83  	VariableCPtr
    84  	
    85  	VariableCPURegister
    86  )
    87  
    88  
    89  
    90  
    91  
    92  type Variable struct {
    93  	Name string
    94  	*internalVariable
    95  }
    96  
    97  
    98  
    99  
   100  
   101  
   102  
   103  
   104  
   105  
   106  type internalVariable struct {
   107  	Addr      uint64
   108  	OnlyAddr  bool
   109  	DwarfType godwarf.Type
   110  	RealType  godwarf.Type
   111  	Kind      reflect.Kind
   112  	Mem       memory.MemoryReader
   113  	bi        *binary_info.BinaryInfo
   114  
   115  	Value        constant.Value
   116  	FloatSpecial floatSpecial
   117  
   118  	
   119  	FunctionName string
   120  	FileName     string
   121  	Line         int
   122  
   123  	Len int64
   124  	Cap int64
   125  
   126  	Flags variableFlags
   127  
   128  	
   129  	
   130  	
   131  	
   132  	Base      uint64
   133  	stride    int64
   134  	fieldType godwarf.Type
   135  
   136  	
   137  	closureAddr uint64
   138  
   139  	Children []*Variable
   140  
   141  	loaded           bool
   142  	needsUpdate      bool
   143  	Unreadable       error
   144  	ObjectDumpConfig config.ObjectDumpConfig
   145  	dictAddr         uint64
   146  	reg              *op.DwarfRegister 
   147  
   148  	mapIter *mapIterator
   149  
   150  	VariablesCache *VariablesCache
   151  	inPool         bool
   152  }
   153  
   154  func NewVariable(name string, addr uint64, dwarfType godwarf.Type, mem memory.MemoryReader, bi *binary_info.BinaryInfo, objectDumpConfig config.ObjectDumpConfig, dictAddr uint64, variablesCache *VariablesCache) (v *Variable) {
   155  	defer func() {
   156  		if r := recover(); r != nil {
   157  			logger.Logger().Fatalf("Caught panic while creating variable. Variable: %s, recovered: %v\n", name, r)
   158  			var err error
   159  			if e, ok := r.(error); ok {
   160  				err = e
   161  			} else {
   162  				err = rookoutErrors.NewVariableCreationFailed(r)
   163  			}
   164  			v = &Variable{Name: name, internalVariable: &internalVariable{Unreadable: err}}
   165  		}
   166  	}()
   167  
   168  	var err error
   169  	dwarfType, err = resolveParametricType(bi, mem, dwarfType, dictAddr)
   170  	if err != nil {
   171  		
   172  		logger.Logger().Debugf("could not resolve parametric type of %s", name)
   173  	}
   174  
   175  	if styp, isstruct := dwarfType.(*godwarf.StructType); isstruct && !strings.Contains(styp.Name, "<") && !strings.Contains(styp.Name, "{") {
   176  		
   177  		
   178  		
   179  		
   180  		
   181  		
   182  		
   183  		
   184  		
   185  		
   186  		
   187  		
   188  		
   189  		
   190  		
   191  		cu := bi.Images[dwarfType.Common().Index].FindCompileUnitForOffset(dwarfType.Common().Offset)
   192  		if cu != nil && cu.IsGo {
   193  			dwarfType = &godwarf.TypedefType{
   194  				CommonType: *(dwarfType.Common()),
   195  				Type:       dwarfType,
   196  			}
   197  		}
   198  	}
   199  
   200  	if v, ok := variablesCache.get(addr, dwarfType, mem); ok {
   201  		v.UpdateObjectDumpConfig(config.MaxObjectDumpConfig(v.ObjectDumpConfig, objectDumpConfig))
   202  		return &Variable{Name: name, internalVariable: v}
   203  	}
   204  
   205  	v = &Variable{internalVariable: variablesPool.get()}
   206  	v.VariablesCache = variablesCache
   207  	v.Name = name
   208  	v.Addr = addr
   209  	v.DwarfType = dwarfType
   210  	v.bi = bi
   211  	v.Mem = mem
   212  	v.ObjectDumpConfig = objectDumpConfig
   213  	v.dictAddr = dictAddr
   214  	v.RealType = resolveTypedef(dwarfType)
   215  
   216  	variablesCache.set(v.internalVariable)
   217  
   218  	switch t := v.RealType.(type) {
   219  	case *godwarf.PtrType:
   220  		v.Kind = reflect.Ptr
   221  		if _, isvoid := t.Type.(*godwarf.VoidType); isvoid {
   222  			v.Kind = reflect.UnsafePointer
   223  		} else if isCgoType(bi, t) {
   224  			v.Flags |= VariableCPtr
   225  			v.fieldType = t.Type
   226  			v.stride = alignAddr(v.fieldType.Size(), v.fieldType.Align())
   227  			v.Len = 0
   228  			if isCgoCharPtr(bi, t) {
   229  				v.Kind = reflect.String
   230  			}
   231  			if v.Addr != 0 {
   232  				v.Base, v.Unreadable = readUintRaw(v.Mem, v.Addr, int64(v.bi.PointerSize))
   233  			}
   234  		}
   235  	case *godwarf.ChanType:
   236  		v.Kind = reflect.Chan
   237  		if v.Addr != 0 {
   238  			v.loadChanInfo()
   239  		}
   240  	case *godwarf.MapType:
   241  		v.Kind = reflect.Map
   242  	case *godwarf.StringType:
   243  		v.Kind = reflect.String
   244  		v.stride = 1
   245  		v.fieldType = &godwarf.UintType{BasicType: godwarf.BasicType{CommonType: godwarf.CommonType{ByteSize: 1, Name: "byte"}, BitSize: 8, BitOffset: 0}}
   246  		if v.Addr != 0 {
   247  			v.Base, v.Len, v.Unreadable = readStringInfo(v.Mem, v.bi, v.Addr, t)
   248  		}
   249  	case *godwarf.SliceType:
   250  		v.Kind = reflect.Slice
   251  		if v.Addr != 0 {
   252  			v.loadSliceInfo(t)
   253  		}
   254  	case *godwarf.InterfaceType:
   255  		v.Kind = reflect.Interface
   256  	case *godwarf.StructType:
   257  		v.Kind = reflect.Struct
   258  	case *godwarf.ArrayType:
   259  		v.Kind = reflect.Array
   260  		v.Base = v.Addr
   261  		v.Len = t.Count
   262  		v.Cap = -1
   263  		v.fieldType = t.Type
   264  		v.stride = 0
   265  
   266  		if t.Count > 0 {
   267  			v.stride = t.ByteSize / t.Count
   268  		}
   269  	case *godwarf.ComplexType:
   270  		switch t.ByteSize {
   271  		case 8:
   272  			v.Kind = reflect.Complex64
   273  		case 16:
   274  			v.Kind = reflect.Complex128
   275  		}
   276  	case *godwarf.IntType:
   277  		v.Kind = reflect.Int
   278  	case *godwarf.CharType:
   279  		
   280  		// godwarf.IntType.
   281  		v.RealType = &godwarf.IntType{BasicType: t.BasicType}
   282  		v.Kind = reflect.Int
   283  	case *godwarf.UcharType:
   284  		v.RealType = &godwarf.IntType{BasicType: t.BasicType}
   285  		v.Kind = reflect.Int
   286  	case *godwarf.UintType:
   287  		v.Kind = reflect.Uint
   288  	case *godwarf.FloatType:
   289  		switch t.ByteSize {
   290  		case 4:
   291  			v.Kind = reflect.Float32
   292  		case 8:
   293  			v.Kind = reflect.Float64
   294  		}
   295  	case *godwarf.BoolType:
   296  		v.Kind = reflect.Bool
   297  	case *godwarf.FuncType:
   298  		v.Kind = reflect.Func
   299  	case *godwarf.VoidType:
   300  		v.Kind = reflect.Invalid
   301  	case *godwarf.UnspecifiedType:
   302  		v.Kind = reflect.Invalid
   303  	default:
   304  		v.Unreadable = fmt.Errorf("unknown type: %T", t)
   305  	}
   306  
   307  	return v
   308  }
   309  
   310  func (v *Variable) spawn(name string, addr uint64, dwarfType godwarf.Type, mem memory.MemoryReader) *Variable {
   311  	return NewVariable(name, addr, dwarfType, mem, v.bi, v.ObjectDumpConfig, v.dictAddr, v.VariablesCache)
   312  }
   313  
   314  func resolveTypedef(typ godwarf.Type) godwarf.Type {
   315  	for {
   316  		switch tt := typ.(type) {
   317  		case *godwarf.TypedefType:
   318  			typ = tt.Type
   319  		case *godwarf.QualType:
   320  			typ = tt.Type
   321  		default:
   322  			return typ
   323  		}
   324  	}
   325  }
   326  
   327  
   328  func isCgoType(bi *binary_info.BinaryInfo, typ godwarf.Type) bool {
   329  	cu := bi.Images[typ.Common().Index].FindCompileUnitForOffset(typ.Common().Offset)
   330  	if cu == nil {
   331  		return false
   332  	}
   333  	return !cu.IsGo
   334  }
   335  
   336  
   337  func isCgoCharPtr(bi *binary_info.BinaryInfo, typ *godwarf.PtrType) bool {
   338  	if !isCgoType(bi, typ) {
   339  		return false
   340  	}
   341  
   342  	fieldtyp := typ.Type
   343  resolveQualTypedef:
   344  	for {
   345  		switch t := fieldtyp.(type) {
   346  		case *godwarf.QualType:
   347  			fieldtyp = t.Type
   348  		case *godwarf.TypedefType:
   349  			fieldtyp = t.Type
   350  		default:
   351  			break resolveQualTypedef
   352  		}
   353  	}
   354  
   355  	_, ischar := fieldtyp.(*godwarf.CharType)
   356  	_, isuchar := fieldtyp.(*godwarf.UcharType)
   357  	return ischar || isuchar
   358  }
   359  
   360  
   361  func alignAddr(addr, align int64) int64 {
   362  	return (addr + int64(align-1)) &^ int64(align-1)
   363  }
   364  
   365  
   366  
   367  func (v *Variable) loadChanInfo() {
   368  	chanType, ok := v.RealType.(*godwarf.ChanType)
   369  	if !ok {
   370  		v.Unreadable = errors.New("bad channel type")
   371  		return
   372  	}
   373  	sv := v.clone()
   374  	sv.RealType = resolveTypedef(&(chanType.TypedefType))
   375  	sv = sv.MaybeDereference()
   376  	if sv.Unreadable != nil || sv.Addr == 0 {
   377  		return
   378  	}
   379  	v.Base = sv.Addr
   380  	structType, ok := sv.DwarfType.(*godwarf.StructType)
   381  	if !ok {
   382  		v.Unreadable = errors.New("bad channel type")
   383  		return
   384  	}
   385  
   386  	lenAddr, _ := sv.toField(structType.Field[1])
   387  	lenAddr.LoadValue()
   388  	if lenAddr.Unreadable != nil {
   389  		v.Unreadable = fmt.Errorf("unreadable length: %v", lenAddr.Unreadable)
   390  		return
   391  	}
   392  	chanLen, _ := constant.Uint64Val(lenAddr.Value)
   393  
   394  	for i := range structType.Field {
   395  		field := structType.Field[i]
   396  		if field.Name == "buf" {
   397  			field.Type = pointerTo(fakeArrayType(chanLen, chanType.ElemType), v.bi)
   398  		}
   399  		structType.Field[i] = field
   400  	}
   401  
   402  	v.RealType = &godwarf.ChanType{
   403  		TypedefType: godwarf.TypedefType{
   404  			CommonType: chanType.TypedefType.CommonType,
   405  			Type:       pointerTo(structType, v.bi),
   406  		},
   407  		ElemType: chanType.ElemType,
   408  	}
   409  }
   410  
   411  func (v *Variable) clone() *Variable {
   412  	r := *v
   413  	internalR := *v.internalVariable
   414  	r.internalVariable = &internalR
   415  	return &r
   416  }
   417  
   418  const (
   419  	sliceArrayFieldName = "array"
   420  	sliceLenFieldName   = "len"
   421  	sliceCapFieldName   = "cap"
   422  )
   423  
   424  func (v *Variable) loadSliceInfo(t *godwarf.SliceType) {
   425  	var err error
   426  	for _, f := range t.Field {
   427  		switch f.Name {
   428  		case sliceArrayFieldName:
   429  			var base uint64
   430  			base, err = readUintRaw(v.Mem, uint64(int64(v.Addr)+f.ByteOffset), f.Type.Size())
   431  			if err == nil {
   432  				v.Base = base
   433  				
   434  				ptrType, ok := f.Type.(*godwarf.PtrType)
   435  				if !ok {
   436  					v.Unreadable = fmt.Errorf("Invalid type %s in slice array", f.Type)
   437  					return
   438  				}
   439  				v.fieldType = ptrType.Type
   440  			}
   441  		case sliceLenFieldName:
   442  			lstrAddr, _ := v.toField(f)
   443  			lstrAddr.LoadValue()
   444  			err = lstrAddr.Unreadable
   445  			if err == nil {
   446  				v.Len, _ = constant.Int64Val(lstrAddr.Value)
   447  			}
   448  		case sliceCapFieldName:
   449  			cstrAddr, _ := v.toField(f)
   450  			cstrAddr.LoadValue()
   451  			err = cstrAddr.Unreadable
   452  			if err == nil {
   453  				v.Cap, _ = constant.Int64Val(cstrAddr.Value)
   454  			}
   455  		}
   456  		if err != nil {
   457  			v.Unreadable = err
   458  			return
   459  		}
   460  	}
   461  
   462  	v.stride = v.fieldType.Size()
   463  	if t, ok := v.fieldType.(*godwarf.PtrType); ok {
   464  		v.stride = t.ByteSize
   465  	}
   466  }
   467  
   468  func (v *Variable) toField(field *godwarf.StructField) (*Variable, error) {
   469  	if v.Unreadable != nil {
   470  		return v.clone(), nil
   471  	}
   472  	if v.Addr == 0 {
   473  		return nil, errors.New("variable addrExecutor is nil")
   474  	}
   475  
   476  	name := ""
   477  	if v.Name != "" {
   478  		parts := strings.Split(field.Name, ".")
   479  		if len(parts) > 1 {
   480  			name = fmt.Sprintf("%s.%s", v.Name, parts[1])
   481  		} else {
   482  			name = fmt.Sprintf("%s.%s", v.Name, field.Name)
   483  		}
   484  	}
   485  	return v.spawn(name, uint64(int64(v.Addr)+field.ByteOffset), field.Type, v.Mem), nil
   486  }
   487  
   488  
   489  func (v *Variable) MaybeDereference() *Variable {
   490  	if v.Unreadable != nil {
   491  		return v
   492  	}
   493  
   494  	switch t := v.RealType.(type) {
   495  	case *godwarf.PtrType:
   496  		if v.Addr == 0 && len(v.Children) == 1 && v.loaded {
   497  			
   498  			return v.Children[0]
   499  		}
   500  		ptrval, err := readUintRaw(v.Mem, v.Addr, t.ByteSize)
   501  		r := v.spawn(v.Name, ptrval, t.Type, memory.DereferenceMemory(v.Mem))
   502  		if err != nil {
   503  			r.Unreadable = err
   504  		}
   505  
   506  		return r
   507  	default:
   508  		return v
   509  	}
   510  }
   511  
   512  func (v *internalVariable) UpdateObjectDumpConfig(newConfig config.ObjectDumpConfig) {
   513  	v.needsUpdate = !(v.ObjectDumpConfig.MaxWidth == newConfig.MaxWidth &&
   514  		v.ObjectDumpConfig.MaxDepth == newConfig.MaxDepth &&
   515  		v.ObjectDumpConfig.MaxString == newConfig.MaxString &&
   516  		v.ObjectDumpConfig.MaxCollectionDepth == newConfig.MaxCollectionDepth)
   517  	v.ObjectDumpConfig = newConfig
   518  }
   519  
   520  
   521  func (v *Variable) LoadValue() {
   522  	v.LoadValueInternal(0)
   523  }
   524  
   525  func (v *Variable) LoadValueInternal(recurseLevel int) error {
   526  	defer func() {
   527  		v.loaded = true
   528  		v.needsUpdate = false
   529  
   530  		if r := recover(); r != nil {
   531  			logger.Logger().Fatalf("Caught panic while loading variable. Variable: %s, recovered: %v\n", v.Name, r)
   532  			var err error
   533  			if e, ok := r.(error); ok {
   534  				err = e
   535  			} else {
   536  				err = rookoutErrors.NewVariableLoadFailed(r)
   537  			}
   538  			v.Unreadable = err
   539  		}
   540  	}()
   541  
   542  	if v.Unreadable != nil || (v.Addr == 0 && v.Base == 0) {
   543  		return v.Unreadable
   544  	}
   545  	if v.loaded && !v.needsUpdate {
   546  		return nil
   547  	}
   548  
   549  	increaseDepth := v.loaded && v.needsUpdate
   550  	if increaseDepth {
   551  		for _, child := range v.Children {
   552  			child.UpdateObjectDumpConfig(config.MaxObjectDumpConfig(v.ObjectDumpConfig, child.ObjectDumpConfig))
   553  		}
   554  	}
   555  
   556  	switch v.Kind {
   557  	case reflect.Ptr, reflect.UnsafePointer:
   558  		if !increaseDepth {
   559  			v.Len = 1
   560  			v.Children = []*Variable{v.MaybeDereference()}
   561  		}
   562  		
   563  		
   564  		nextLvl := recurseLevel
   565  		if v.Children[0].Kind == reflect.Interface {
   566  			nextLvl++
   567  		}
   568  		err := v.Children[0].LoadValueInternal(nextLvl)
   569  		if err != nil {
   570  			return err
   571  		}
   572  
   573  	case reflect.Chan:
   574  		sv := v.clone()
   575  		sv.RealType = resolveTypedef(&(sv.RealType.(*godwarf.ChanType).TypedefType))
   576  		sv = sv.MaybeDereference()
   577  		err := sv.LoadValueInternal(recurseLevel)
   578  		if err != nil {
   579  			return err
   580  		}
   581  		v.Children = sv.Children
   582  		v.Len = sv.Len
   583  		v.Base = sv.Addr
   584  
   585  	case reflect.Map:
   586  		if recurseLevel <= v.ObjectDumpConfig.MaxDepth {
   587  			err := v.loadMap(recurseLevel)
   588  			if err != nil {
   589  				return err
   590  			}
   591  		} else {
   592  			
   593  			if v.mapIter == nil {
   594  				var err error
   595  				v.mapIter, err = v.newMapIterator()
   596  				if err != nil {
   597  					return err
   598  				}
   599  			}
   600  		}
   601  
   602  	case reflect.String:
   603  		var val string
   604  		switch {
   605  		case v.Flags&VariableCPtr != 0:
   606  			var done bool
   607  			val, done, v.Unreadable = readCStringValue(memory.DereferenceMemory(v.Mem), v.Base, v.ObjectDumpConfig)
   608  			if v.Unreadable == nil {
   609  				v.Len = int64(len(val))
   610  				if !done {
   611  					v.Len++
   612  				}
   613  			}
   614  
   615  		case v.Flags&VariableCPURegister != 0:
   616  			if increaseDepth {
   617  				
   618  				break
   619  			}
   620  
   621  			val = fmt.Sprintf("%x", v.reg.Bytes)
   622  			s := v.Base - memory.FakeAddress
   623  			if s < uint64(len(val)) {
   624  				val = val[s:]
   625  				if v.Len >= 0 && v.Len < int64(len(val)) {
   626  					val = val[:v.Len]
   627  				}
   628  			}
   629  
   630  		default:
   631  			val, v.Unreadable = readStringValue(memory.DereferenceMemory(v.Mem), v.Base, v.Len, v.ObjectDumpConfig)
   632  		}
   633  		v.Value = constant.MakeString(val)
   634  
   635  	case reflect.Slice, reflect.Array:
   636  		if increaseDepth {
   637  			
   638  			for _, child := range v.Children {
   639  				child.LoadValueInternal(recurseLevel + 1)
   640  			}
   641  		}
   642  
   643  		v.loadArrayValues(recurseLevel)
   644  
   645  	case reflect.Struct:
   646  		v.Mem = memory.CacheMemory(v.Mem, v.Addr, int(v.RealType.Size()))
   647  		t := v.RealType.(*godwarf.StructType)
   648  		v.Len = int64(len(t.Field))
   649  
   650  		if recurseLevel >= v.ObjectDumpConfig.MaxDepth {
   651  			return nil
   652  		}
   653  
   654  		
   655  		if len(v.Children) != len(t.Field) {
   656  			v.Children = make([]*Variable, 0, len(t.Field))
   657  			for i := range t.Field {
   658  				f, _ := v.toField(t.Field[i])
   659  				v.Children = append(v.Children, f)
   660  				v.Children[i].Name = t.Field[i].Name
   661  				v.Children[i].LoadValueInternal(recurseLevel + 1)
   662  			}
   663  		} else if increaseDepth {
   664  			
   665  			for i := range v.Children {
   666  				v.Children[i].LoadValueInternal(recurseLevel + 1)
   667  			}
   668  		}
   669  
   670  	case reflect.Interface:
   671  		if increaseDepth && v.Children != nil && recurseLevel <= v.ObjectDumpConfig.MaxDepth {
   672  			v.Children[0].LoadValueInternal(recurseLevel)
   673  		}
   674  		v.loadInterface(recurseLevel, true)
   675  
   676  	case reflect.Complex64, reflect.Complex128:
   677  		if increaseDepth {
   678  			
   679  			break
   680  		}
   681  
   682  		v.readComplex(v.RealType.(*godwarf.ComplexType).ByteSize)
   683  	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
   684  		if increaseDepth {
   685  			
   686  			break
   687  		}
   688  
   689  		var val int64
   690  		val, v.Unreadable = readIntRaw(v.Mem, v.Addr, v.RealType.(*godwarf.IntType).ByteSize)
   691  		v.Value = constant.MakeInt64(val)
   692  	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
   693  		if increaseDepth {
   694  			
   695  			break
   696  		}
   697  
   698  		if v.Flags&VariableCPURegister != 0 {
   699  			v.Value = constant.MakeUint64(v.reg.Uint64Val)
   700  		} else {
   701  			var val uint64
   702  			val, v.Unreadable = readUintRaw(v.Mem, v.Addr, v.RealType.(*godwarf.UintType).ByteSize)
   703  			v.Value = constant.MakeUint64(val)
   704  		}
   705  
   706  	case reflect.Bool:
   707  		if increaseDepth {
   708  			
   709  			break
   710  		}
   711  
   712  		val := make([]byte, 1)
   713  		_, err := v.Mem.ReadMemory(val, v.Addr)
   714  		v.Unreadable = err
   715  		if err == nil {
   716  			v.Value = constant.MakeBool(val[0] != 0)
   717  		}
   718  	case reflect.Float32, reflect.Float64:
   719  		if increaseDepth {
   720  			
   721  			break
   722  		}
   723  
   724  		var val float64
   725  		val, v.Unreadable = v.readFloatRaw(v.RealType.(*godwarf.FloatType).ByteSize)
   726  		v.Value = constant.MakeFloat64(val)
   727  		switch {
   728  		case math.IsInf(val, +1):
   729  			v.FloatSpecial = FloatIsPosInf
   730  		case math.IsInf(val, -1):
   731  			v.FloatSpecial = FloatIsNegInf
   732  		case math.IsNaN(val):
   733  			v.FloatSpecial = FloatIsNaN
   734  		}
   735  	case reflect.Func:
   736  		if increaseDepth {
   737  			
   738  			break
   739  		}
   740  
   741  		v.readFunctionPtr()
   742  	default:
   743  		v.Unreadable = fmt.Errorf("unknown or unsupported kind: \"%s\"", v.Kind.String())
   744  	}
   745  
   746  	return nil
   747  }
   748  
   749  type floatSpecial uint8
   750  
   751  const (
   752  	
   753  	FloatIsNormal floatSpecial = iota
   754  	
   755  	FloatIsNaN
   756  	
   757  	FloatIsPosInf
   758  	
   759  	FloatIsNegInf
   760  )
   761  
   762  func (v *Variable) readFloatRaw(size int64) (float64, error) {
   763  	val := make([]byte, int(size))
   764  	_, err := v.Mem.ReadMemory(val, v.Addr)
   765  	if err != nil {
   766  		return 0.0, err
   767  	}
   768  	buf := bytes.NewBuffer(val)
   769  
   770  	switch size {
   771  	case 4:
   772  		n := float32(0)
   773  		binary.Read(buf, binary.LittleEndian, &n)
   774  		return float64(n), nil
   775  	case 8:
   776  		n := float64(0)
   777  		binary.Read(buf, binary.LittleEndian, &n)
   778  		return n, nil
   779  	}
   780  
   781  	return 0.0, fmt.Errorf("could not read float")
   782  }
   783  
   784  func (v *Variable) readFunctionPtr() {
   785  	
   786  	v.closureAddr = v.funcvalAddr()
   787  	if v.Unreadable != nil {
   788  		return
   789  	}
   790  	if v.closureAddr == 0 {
   791  		v.Base = 0
   792  		v.Value = constant.MakeString("")
   793  		return
   794  	}
   795  
   796  	val, err := readUintRaw(v.Mem, v.closureAddr, int64(v.bi.PointerSize))
   797  	if err != nil {
   798  		v.Unreadable = err
   799  		return
   800  	}
   801  
   802  	v.Base = val
   803  	file, line, fn := v.bi.PCToLine(uint64(v.Base))
   804  	if fn == nil {
   805  		v.Unreadable = fmt.Errorf("could not find function for %#v", v.Base)
   806  		return
   807  	}
   808  
   809  	v.FunctionName = fn.Name
   810  	v.FileName = file
   811  	v.Line = line
   812  }
   813  
   814  
   815  func (v *Variable) funcvalAddr() uint64 {
   816  	val, err := readUintRaw(v.Mem, v.Addr, int64(v.bi.PointerSize))
   817  	if err != nil {
   818  		v.Unreadable = err
   819  		return 0
   820  	}
   821  	return val
   822  }
   823  
   824  func (v *Variable) loadMap(recurseLevel int) error {
   825  	if v.mapIter == nil {
   826  		var err error
   827  		v.mapIter, err = v.newMapIterator()
   828  		if err != nil {
   829  			return err
   830  		}
   831  	}
   832  
   833  	if v.Len == 0 || v.ObjectDumpConfig.MaxWidth == 0 {
   834  		return nil
   835  	}
   836  
   837  	childrenLen := int(v.Len)
   838  	if childrenLen > v.ObjectDumpConfig.MaxWidth {
   839  		childrenLen = v.ObjectDumpConfig.MaxWidth
   840  	}
   841  	if v.Children == nil {
   842  		
   843  		v.Children = make([]*Variable, 0, childrenLen*2)
   844  	}
   845  	for v.mapIter.next() {
   846  		key := v.mapIter.key()
   847  		var val *Variable
   848  		if v.mapIter.values.fieldType.Size() > 0 {
   849  			val = v.mapIter.value()
   850  		} else {
   851  			val = v.spawn("", v.mapIter.values.Addr, v.mapIter.values.fieldType, memory.DereferenceMemory(v.Mem))
   852  		}
   853  		key.LoadValueInternal(recurseLevel + 1)
   854  		val.LoadValueInternal(recurseLevel + 1)
   855  		v.Children = append(v.Children, key, val)
   856  		if len(v.Children)/2 >= childrenLen {
   857  			break
   858  		}
   859  	}
   860  	return nil
   861  }
   862  
   863  func (v *Variable) LoadStructValue(name string) (*Variable, error) {
   864  	if v.Kind != reflect.Struct {
   865  		return nil, rookoutErrors.NewVariableIsNotStruct(v.Name, v.Kind)
   866  	}
   867  
   868  	t := v.RealType.(*godwarf.StructType)
   869  	for i := range t.Field {
   870  		if t.Field[i].Name != name {
   871  			continue
   872  		}
   873  
   874  		f, _ := v.toField(t.Field[i])
   875  		v.Children = append(v.Children, f)
   876  		v.Children[i].Name = t.Field[i].Name
   877  		v.Children[i].LoadValue()
   878  		return v.Children[i], nil
   879  	}
   880  
   881  	return nil, rookoutErrors.NewNoSuchMember(v.Name, name)
   882  }
   883  func (v *Variable) LoadMapValue(key string) (*Variable, error) {
   884  	if v.Kind != reflect.Map {
   885  		return nil, rookoutErrors.NewVariableIsNotMap(v.Name, v.Kind)
   886  	}
   887  
   888  	if v.mapIter == nil {
   889  		var err error
   890  		v.mapIter, err = v.newMapIterator()
   891  		if err != nil {
   892  			return nil, err
   893  		}
   894  	}
   895  
   896  	for v.mapIter.next() {
   897  		
   898  		keyVar := v.mapIter.key()
   899  		var valVar *Variable
   900  		if v.mapIter.values.fieldType.Size() > 0 {
   901  			valVar = v.mapIter.value()
   902  		} else {
   903  			valVar = v.spawn("", v.mapIter.values.Addr, v.mapIter.values.fieldType, memory.DereferenceMemory(v.Mem))
   904  		}
   905  		v.Children = append(v.Children, keyVar, valVar)
   906  
   907  		
   908  		if keyVar.Unreadable != nil {
   909  			continue
   910  		}
   911  		if keyVar.Kind == reflect.Interface || keyVar.Kind == reflect.Ptr {
   912  			
   913  			keyVar.ObjectDumpConfig.MaxCollectionDepth = 1
   914  			keyVar.LoadValue()
   915  			keyVar = keyVar.Children[0]
   916  		}
   917  		if keyVar.Kind != reflect.String {
   918  			continue
   919  		}
   920  
   921  		keyVar.LoadValue()
   922  		
   923  		if keyVar.Unreadable != nil || constant.StringVal(keyVar.Value) != key {
   924  			continue
   925  		}
   926  
   927  		
   928  		valVar.UpdateObjectDumpConfig(config.TailorObjectDumpConfig(valVar.Kind, int(valVar.Len)))
   929  		valVar.LoadValue()
   930  		return valVar, nil
   931  	}
   932  
   933  	return nil, rookoutErrors.NewKeyNotInMap(v.Name, key)
   934  }
   935  
   936  func pointerTo(typ godwarf.Type, bi *binary_info.BinaryInfo) godwarf.Type {
   937  	return &godwarf.PtrType{
   938  		CommonType: godwarf.CommonType{
   939  			ByteSize:    int64(bi.PointerSize),
   940  			Name:        "*" + typ.Common().Name,
   941  			ReflectKind: reflect.Ptr,
   942  			Offset:      0,
   943  		},
   944  		Type: typ,
   945  	}
   946  }
   947  
   948  
   949  func fakeArrayType(n uint64, fieldType godwarf.Type) godwarf.Type {
   950  	stride := alignAddr(fieldType.Common().ByteSize, fieldType.Align())
   951  	return &godwarf.ArrayType{
   952  		CommonType: godwarf.CommonType{
   953  			ReflectKind: reflect.Array,
   954  			ByteSize:    int64(n) * stride,
   955  			Name:        fmt.Sprintf("[%d]%s", n, fieldType.String())},
   956  		Type:          fieldType,
   957  		StrideBitSize: stride * 8,
   958  		Count:         int64(n)}
   959  }
   960  
   961  func (v *Variable) asInt() (int64, error) {
   962  	if v.DwarfType == nil {
   963  		if v.Value.Kind() != constant.Int {
   964  			return 0, fmt.Errorf("can not convert constant %s to int", v.Value)
   965  		}
   966  	} else {
   967  		v.LoadValue()
   968  		if v.Unreadable != nil {
   969  			return 0, v.Unreadable
   970  		}
   971  		if _, ok := v.DwarfType.(*godwarf.IntType); !ok {
   972  			return 0, fmt.Errorf("can not convert value of type %s to int", v.DwarfType.String())
   973  		}
   974  	}
   975  	n, _ := constant.Int64Val(v.Value)
   976  	return n, nil
   977  }
   978  
   979  func (v *Variable) asUint() (uint64, error) {
   980  	if v.DwarfType == nil {
   981  		if v.Value.Kind() != constant.Int {
   982  			return 0, fmt.Errorf("can not convert constant %s to uint", v.Value)
   983  		}
   984  	} else {
   985  		v.LoadValue()
   986  		if v.Unreadable != nil {
   987  			return 0, v.Unreadable
   988  		}
   989  		if _, ok := v.DwarfType.(*godwarf.UintType); !ok {
   990  			return 0, fmt.Errorf("can not convert value of type %s to uint", v.DwarfType.String())
   991  		}
   992  	}
   993  	n, _ := constant.Uint64Val(v.Value)
   994  	return n, nil
   995  }
   996  
   997  const maxArrayStridePrefetch = 1024 
   998  
   999  func (v *Variable) loadArrayValues(recurseLevel int) {
  1000  	if v.Unreadable != nil {
  1001  		return
  1002  	}
  1003  	if v.Len < 0 {
  1004  		v.Unreadable = errors.New("Negative array length")
  1005  		return
  1006  	}
  1007  
  1008  	count := v.Len
  1009  	
  1010  	if count > int64(v.ObjectDumpConfig.MaxWidth) {
  1011  		count = int64(v.ObjectDumpConfig.MaxWidth)
  1012  	}
  1013  
  1014  	if v.stride < maxArrayStridePrefetch {
  1015  		v.Mem = memory.CacheMemory(v.Mem, v.Base, int(v.stride*count))
  1016  	}
  1017  
  1018  	mem := v.Mem
  1019  	if v.Kind != reflect.Array {
  1020  		mem = memory.DereferenceMemory(mem)
  1021  	}
  1022  
  1023  	if v.Children == nil {
  1024  		
  1025  		v.Children = make([]*Variable, 0, count)
  1026  	}
  1027  
  1028  	for i := int64(len(v.Children)); i < count; i++ {
  1029  		fieldvar := v.spawn("", uint64(int64(v.Base)+(i*v.stride)), v.fieldType, mem)
  1030  		fieldvar.LoadValueInternal(recurseLevel + 1)
  1031  		v.Children = append(v.Children, fieldvar)
  1032  	}
  1033  }
  1034  
  1035  func (v *Variable) loadInterface(recurseLevel int, loadData bool) {
  1036  	_type, data, isnil := v.readInterface()
  1037  
  1038  	if isnil {
  1039  		if data == nil {
  1040  			return
  1041  		}
  1042  
  1043  		
  1044  		data = data.MaybeDereference()
  1045  		v.Children = []*Variable{data}
  1046  		if loadData {
  1047  			v.Children[0].LoadValueInternal(recurseLevel)
  1048  		}
  1049  		return
  1050  	}
  1051  
  1052  	if data == nil {
  1053  		v.Unreadable = fmt.Errorf("invalid interface type")
  1054  		return
  1055  	}
  1056  
  1057  	typ, kind, err := runtimeTypeToDIE(_type, data.Addr)
  1058  	if err != nil {
  1059  		v.Unreadable = err
  1060  		return
  1061  	}
  1062  
  1063  	deref := false
  1064  	if kind&kindDirectIface == 0 {
  1065  		realtyp := resolveTypedef(typ)
  1066  		if _, isptr := realtyp.(*godwarf.PtrType); !isptr {
  1067  			typ = pointerTo(typ, v.bi)
  1068  			deref = true
  1069  		}
  1070  	}
  1071  
  1072  	data = v.spawn("data", data.Addr, typ, data.Mem)
  1073  	if deref {
  1074  		data = data.MaybeDereference()
  1075  		data.Name = "data"
  1076  	}
  1077  
  1078  	v.Children = []*Variable{data}
  1079  	if loadData && recurseLevel <= v.ObjectDumpConfig.MaxDepth {
  1080  		v.Children[0].LoadValueInternal(recurseLevel)
  1081  	} else {
  1082  		v.Children[0].OnlyAddr = true
  1083  	}
  1084  }
  1085  
  1086  func (v *Variable) readInterface() (_type, data *Variable, isnil bool) {
  1087  	
  1088  	
  1089  	
  1090  	
  1091  	
  1092  	
  1093  	
  1094  	
  1095  	
  1096  	
  1097  	
  1098  	
  1099  	
  1100  	
  1101  	
  1102  	
  1103  
  1104  	v.Mem = memory.CacheMemory(v.Mem, v.Addr, int(v.RealType.Size()))
  1105  
  1106  	ityp := resolveTypedef(&v.RealType.(*godwarf.InterfaceType).TypedefType).(*godwarf.StructType)
  1107  
  1108  	for _, f := range ityp.Field {
  1109  		switch f.Name {
  1110  		case "tab": 
  1111  			tab, _ := v.toField(f)
  1112  			tab = tab.MaybeDereference()
  1113  			isnil = tab.Addr == 0
  1114  			if !isnil {
  1115  				var err error
  1116  				_type, err = tab.structMember("_type")
  1117  				if err != nil {
  1118  					v.Unreadable = fmt.Errorf("invalid interface type: %v", err)
  1119  					return
  1120  				}
  1121  			}
  1122  		case "_type": 
  1123  			_type, _ = v.toField(f)
  1124  			isnil = _type.MaybeDereference().Addr == 0
  1125  		case "data":
  1126  			data, _ = v.toField(f)
  1127  		}
  1128  	}
  1129  	return _type, data, isnil
  1130  }
  1131  
  1132  func (v *Variable) structMember(memberName string) (*Variable, error) {
  1133  	if v.Unreadable != nil {
  1134  		return v.clone(), nil
  1135  	}
  1136  	vname := v.Name
  1137  	if v.loaded && (v.Flags&VariableFakeAddress) != 0 {
  1138  		for i := range v.Children {
  1139  			if v.Children[i].Name == memberName {
  1140  				return v.Children[i], nil
  1141  			}
  1142  		}
  1143  		return nil, fmt.Errorf("%s has no member %s", vname, memberName)
  1144  	}
  1145  	switch v.Kind {
  1146  	case reflect.Chan:
  1147  		v = v.clone()
  1148  		v.RealType = resolveTypedef(&(v.RealType.(*godwarf.ChanType).TypedefType))
  1149  	case reflect.Interface:
  1150  		v.loadInterface(0, false)
  1151  		if len(v.Children) > 0 {
  1152  			v = v.Children[0]
  1153  		}
  1154  	}
  1155  
  1156  	queue := []*Variable{v}
  1157  	seen := map[string]struct{}{} 
  1158  	first := true
  1159  
  1160  	for len(queue) > 0 {
  1161  		v := queue[0]
  1162  		queue = append(queue[:0], queue[1:]...)
  1163  		if _, isseen := seen[v.RealType.String()]; isseen {
  1164  			continue
  1165  		}
  1166  		seen[v.RealType.String()] = struct{}{}
  1167  
  1168  		structVar := v.MaybeDereference()
  1169  		structVar.Name = v.Name
  1170  		if structVar.Unreadable != nil {
  1171  			return structVar, nil
  1172  		}
  1173  
  1174  		switch t := structVar.RealType.(type) {
  1175  		case *godwarf.StructType:
  1176  			for _, field := range t.Field {
  1177  				if field.Name == memberName {
  1178  					return structVar.toField(field)
  1179  				}
  1180  				isEmbeddedStructMember :=
  1181  					field.Embedded ||
  1182  						(field.Type.Common().Name == field.Name) ||
  1183  						(len(field.Name) > 1 &&
  1184  							field.Name[0] == '*' &&
  1185  							field.Type.Common().Name[1:] == field.Name[1:])
  1186  				if !isEmbeddedStructMember {
  1187  					continue
  1188  				}
  1189  				embeddedVar, err := structVar.toField(field)
  1190  				if err != nil {
  1191  					return nil, err
  1192  				}
  1193  				
  1194  				parts := strings.Split(field.Name, ".")
  1195  				if len(parts) > 1 && parts[1] == memberName {
  1196  					return embeddedVar, nil
  1197  				}
  1198  				embeddedVar.Name = structVar.Name
  1199  				queue = append(queue, embeddedVar)
  1200  			}
  1201  		default:
  1202  			if first {
  1203  				return nil, fmt.Errorf("%s (type %s) is not a struct", vname, structVar.TypeString())
  1204  			}
  1205  		}
  1206  		first = false
  1207  	}
  1208  
  1209  	return nil, fmt.Errorf("%s has no member %s", vname, memberName)
  1210  }
  1211  
  1212  
  1213  
  1214  func (v *Variable) TypeString() string {
  1215  	if v == nilVariable {
  1216  		return "nil"
  1217  	}
  1218  	if v.DwarfType != nil {
  1219  		return v.DwarfType.Common().Name
  1220  	}
  1221  	return v.Kind.String()
  1222  }
  1223  
  1224  var nilVariable = &Variable{
  1225  	Name: "nil",
  1226  	internalVariable: &internalVariable{
  1227  		Addr:     0,
  1228  		Base:     0,
  1229  		Kind:     reflect.Ptr,
  1230  		Children: []*Variable{{internalVariable: &internalVariable{Addr: 0, OnlyAddr: true}}},
  1231  	},
  1232  }
  1233  
  1234  func (v *Variable) readComplex(size int64) {
  1235  	var fs int64
  1236  	switch size {
  1237  	case 8:
  1238  		fs = 4
  1239  	case 16:
  1240  		fs = 8
  1241  	default:
  1242  		v.Unreadable = fmt.Errorf("invalid size (%d) for complex type", size)
  1243  		return
  1244  	}
  1245  
  1246  	ftyp := &godwarf.FloatType{BasicType: godwarf.BasicType{CommonType: godwarf.CommonType{ByteSize: fs, Name: fmt.Sprintf("float%d", fs)}, BitSize: fs * 8, BitOffset: 0}}
  1247  
  1248  	realvar := v.spawn("real", v.Addr, ftyp, v.Mem)
  1249  	imagvar := v.spawn("imaginary", v.Addr+uint64(fs), ftyp, v.Mem)
  1250  	realvar.LoadValue()
  1251  	imagvar.LoadValue()
  1252  	v.Value = constant.BinaryOp(realvar.Value, token.ADD, constant.MakeImag(imagvar.Value))
  1253  }
  1254  
  1255  func (v *Variable) loadFieldNamed(name string) *Variable {
  1256  	v, err := v.structMember(name)
  1257  	if err != nil {
  1258  		return nil
  1259  	}
  1260  	v.LoadValue()
  1261  	if v.Unreadable != nil {
  1262  		return nil
  1263  	}
  1264  	return v
  1265  }
  1266  
  1267  func (v *Variable) fieldVariable(name string) *Variable {
  1268  	if !v.loaded {
  1269  		panic("fieldVariable called on a variable that wasn't loaded")
  1270  	}
  1271  	for i := range v.Children {
  1272  		if child := v.Children[i]; child.Name == name {
  1273  			return child
  1274  		}
  1275  	}
  1276  	return nil
  1277  }
  1278  
  1279  
  1280  func (v *Variable) ConstDescr() string {
  1281  	if v.bi == nil || (v.Flags&VariableConstant != 0) {
  1282  		return ""
  1283  	}
  1284  	ctyp := v.bi.GetConst(v.DwarfType)
  1285  	if ctyp == nil {
  1286  		return ""
  1287  	}
  1288  	if typename := v.DwarfType.Common().Name; strings.Index(typename, ".") < 0 || strings.HasPrefix(typename, "C.") {
  1289  		
  1290  		
  1291  		
  1292  		return ""
  1293  	}
  1294  
  1295  	switch v.Kind {
  1296  	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  1297  		fallthrough
  1298  	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
  1299  		n, _ := constant.Int64Val(v.Value)
  1300  		return ctyp.Describe(n)
  1301  	}
  1302  	return ""
  1303  }
  1304  
  1305  func (v *Variable) Close() error {
  1306  	if v.inPool {
  1307  		return nil
  1308  	}
  1309  	v.inPool = true
  1310  
  1311  	for i := range v.Children {
  1312  		_ = v.Children[i].Close()
  1313  	}
  1314  
  1315  	variablesPool.set(v.internalVariable)
  1316  	return nil
  1317  }
  1318  
  1319  
  1320  func (v *Variable) registerVariableTypeConv(newtyp string) (*Variable, error) {
  1321  	var n = 0
  1322  	for i := 0; i < len(v.reg.Bytes); i += n {
  1323  		child := NewVariable("", 0, nil, v.Mem, v.bi, v.ObjectDumpConfig, v.dictAddr, v.VariablesCache)
  1324  		switch newtyp {
  1325  		case "int8":
  1326  			child.Value = constant.MakeInt64(int64(int8(v.reg.Bytes[i])))
  1327  			n = 1
  1328  		case "int16":
  1329  			child.Value = constant.MakeInt64(int64(int16(binary.LittleEndian.Uint16(v.reg.Bytes[i:]))))
  1330  			n = 2
  1331  		case "int32":
  1332  			child.Value = constant.MakeInt64(int64(int32(binary.LittleEndian.Uint32(v.reg.Bytes[i:]))))
  1333  			n = 4
  1334  		case "int64":
  1335  			child.Value = constant.MakeInt64(int64(binary.LittleEndian.Uint64(v.reg.Bytes[i:])))
  1336  			n = 8
  1337  		case "uint8":
  1338  			child.Value = constant.MakeUint64(uint64(v.reg.Bytes[i]))
  1339  			n = 1
  1340  		case "uint16":
  1341  			child.Value = constant.MakeUint64(uint64(binary.LittleEndian.Uint16(v.reg.Bytes[i:])))
  1342  			n = 2
  1343  		case "uint32":
  1344  			child.Value = constant.MakeUint64(uint64(binary.LittleEndian.Uint32(v.reg.Bytes[i:])))
  1345  			n = 4
  1346  		case "uint64":
  1347  			child.Value = constant.MakeUint64(uint64(binary.LittleEndian.Uint64(v.reg.Bytes[i:])))
  1348  			n = 8
  1349  		case "float32":
  1350  			a := binary.LittleEndian.Uint32(v.reg.Bytes[i:])
  1351  			x := *(*float32)(unsafe.Pointer(&a))
  1352  			child.Value = constant.MakeFloat64(float64(x))
  1353  			n = 4
  1354  		case "float64":
  1355  			a := binary.LittleEndian.Uint64(v.reg.Bytes[i:])
  1356  			x := *(*float64)(unsafe.Pointer(&a))
  1357  			child.Value = constant.MakeFloat64(x)
  1358  			n = 8
  1359  		default:
  1360  			if n == 0 {
  1361  				for _, pfx := range []string{"uint", "int"} {
  1362  					if strings.HasPrefix(newtyp, pfx) {
  1363  						n, _ = strconv.Atoi(newtyp[len(pfx):])
  1364  						break
  1365  					}
  1366  				}
  1367  				if n == 0 || binary_info.Popcnt(uint64(n)) != 1 {
  1368  					return nil, fmt.Errorf("unknown CPU register type conversion to %q", newtyp)
  1369  				}
  1370  				n = n / 8
  1371  			}
  1372  			child.Value = constant.MakeString(fmt.Sprintf("%x", v.reg.Bytes[i:][:n]))
  1373  		}
  1374  		v.Children = append(v.Children, child)
  1375  	}
  1376  
  1377  	v.loaded = true
  1378  	v.Kind = reflect.Array
  1379  	v.Len = int64(len(v.Children))
  1380  	v.Base = memory.FakeAddress
  1381  	v.DwarfType = fakeArrayType(uint64(len(v.Children)), &godwarf.VoidType{CommonType: godwarf.CommonType{ByteSize: int64(n)}})
  1382  	v.RealType = v.DwarfType
  1383  	return v, nil
  1384  }
  1385  
  1386  const (
  1387  	timeTimeWallHasMonotonicBit uint64 = 1 << 63 
  1388  
  1389  	
  1390  	maxAddSeconds = (time.Duration(^uint64(0)>>1) / time.Second) * time.Second 
  1391  
  1392  	wallNsecShift = 30 
  1393  
  1394  	unixTimestampOfWallEpoch = -2682288000 
  1395  )
  1396  
  1397  
  1398  
  1399  func (v *Variable) formatTime() {
  1400  	wallv := v.fieldVariable("wall")
  1401  	extv := v.fieldVariable("ext")
  1402  	if wallv == nil || extv == nil || wallv.Unreadable != nil || extv.Unreadable != nil || wallv.Value == nil || extv.Value == nil {
  1403  		return
  1404  	}
  1405  
  1406  	var loc *time.Location
  1407  
  1408  	locv := v.fieldVariable("loc")
  1409  	if locv != nil && locv.Unreadable == nil {
  1410  		namev := locv.loadFieldNamed("name")
  1411  		if namev != nil && namev.Unreadable == nil {
  1412  			name := constant.StringVal(namev.Value)
  1413  			loc, _ = time.LoadLocation(name)
  1414  		}
  1415  	}
  1416  
  1417  	wall, _ := constant.Uint64Val(wallv.Value)
  1418  	ext, _ := constant.Int64Val(extv.Value)
  1419  
  1420  	hasMonotonic := (wall & timeTimeWallHasMonotonicBit) != 0
  1421  	if hasMonotonic {
  1422  		
  1423  		
  1424  		
  1425  		sec := int64(wall << 1 >> (wallNsecShift + 1)) 
  1426  		t := time.Unix(sec+unixTimestampOfWallEpoch, 0).UTC()
  1427  		if loc != nil {
  1428  			t = t.In(loc)
  1429  		}
  1430  		v.Value = constant.MakeString(fmt.Sprintf("%s, %+d", t.Format(time.RFC3339), ext))
  1431  	} else {
  1432  		
  1433  		var t time.Time
  1434  		for ext > int64(maxAddSeconds/time.Second) {
  1435  			t = t.Add(maxAddSeconds)
  1436  			ext -= int64(maxAddSeconds / time.Second)
  1437  		}
  1438  		t = t.Add(time.Duration(ext) * time.Second)
  1439  		if loc != nil {
  1440  			t = t.In(loc)
  1441  		}
  1442  		v.Value = constant.MakeString(t.Format(time.RFC3339))
  1443  	}
  1444  }
  1445  
  1446  func (v *Variable) IsNil() bool {
  1447  	switch v.Kind {
  1448  	case reflect.Slice, reflect.Map, reflect.Chan, reflect.Func:
  1449  		return v.Base == 0
  1450  	case reflect.Ptr, reflect.Interface:
  1451  		return v.Children[0].Addr == 0
  1452  	}
  1453  
  1454  	return false
  1455  }
  1456  
  1457  func (v *Variable) LoadArrayValue(index int) (*Variable, error) {
  1458  	if v.Kind != reflect.Array {
  1459  		return nil, rookoutErrors.NewVariableIsNotMap(v.Name, v.Kind)
  1460  	}
  1461  
  1462  	if v.Len < 0 {
  1463  		v.Unreadable = errors.New("Negative array length")
  1464  	}
  1465  	if v.Unreadable != nil {
  1466  		return nil, v.Unreadable
  1467  	}
  1468  
  1469  	if v.stride < maxArrayStridePrefetch {
  1470  		v.Mem = memory.CacheMemory(v.Mem, v.Base, int(v.stride*int64(index)))
  1471  	}
  1472  
  1473  	mem := v.Mem
  1474  	if v.Kind != reflect.Array {
  1475  		mem = memory.DereferenceMemory(mem)
  1476  	}
  1477  
  1478  	fieldvar := v.spawn("", uint64(int64(v.Base)+(int64(index)*v.stride)), v.fieldType, mem)
  1479  	fieldvar.UpdateObjectDumpConfig(config.TailorObjectDumpConfig(fieldvar.Kind, int(fieldvar.Len)))
  1480  	fieldvar.LoadValueInternal(1)
  1481  	return fieldvar, nil
  1482  }