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 }