variables.go 26.4 KB
Newer Older
D
Derek Parker 已提交
1
package proc
2 3 4

import (
	"bytes"
D
Derek Parker 已提交
5
	"debug/dwarf"
6
	"debug/gosym"
7 8
	"encoding/binary"
	"fmt"
9 10 11
	"go/ast"
	"go/parser"
	"go/token"
12 13 14 15 16
	"strconv"
	"strings"
	"unsafe"

	"github.com/derekparker/delve/dwarf/op"
17
	"github.com/derekparker/delve/dwarf/reader"
18 19
)

20
const (
21 22
	maxVariableRecurse = 1  // How far to recurse when evaluating nested types.
	maxArrayValues     = 64 // Max value for reading large arrays.
23
	maxErrCount        = 3  // Max number of read errors to accept while evaluating slices, arrays and structs
24 25 26

	ChanRecv = "chan receive"
	ChanSend = "chan send"
27 28
)

29
// Represents a variable.
30
type Variable struct {
31 32 33 34 35 36 37 38 39 40 41 42
	Addr      uintptr
	Name      string
	Value     string
	Type      string
	dwarfType dwarf.Type
	thread    *Thread

	Len       int64
	Cap       int64
	base      uintptr
	stride    int64
	fieldType dwarf.Type
43 44
}

45
// Represents a runtime M (OS thread) structure.
46
type M struct {
47 48 49 50
	procid   int     // Thread ID or port.
	spinning uint8   // Busy looping.
	blocked  uint8   // Waiting on futex / semaphore.
	curg     uintptr // Current G running on this thread.
51 52
}

53 54 55 56 57 58 59 60 61 62 63 64 65
const (
	// G status, from: src/runtime/runtime2.go
	Gidle            uint64 = iota // 0
	Grunnable                      // 1 runnable and on a run queue
	Grunning                       // 2
	Gsyscall                       // 3
	Gwaiting                       // 4
	Gmoribund_unused               // 5 currently unused, but hardcoded in gdb scripts
	Gdead                          // 6
	Genqueue                       // 7 Only the Gscanenqueue is used.
	Gcopystack                     // 8 in this state when newstack is moving the stack
)

66 67
// Represents a runtime G (goroutine) structure (at least the
// fields that Delve is interested in).
D
Derek Parker 已提交
68
type G struct {
69 70 71 72 73
	Id         int    // Goroutine ID
	PC         uint64 // PC of goroutine when it was parked.
	SP         uint64 // SP of goroutine when it was parked.
	GoPC       uint64 // PC of 'go' statement that created this goroutine.
	WaitReason string // Reason for goroutine being parked.
74
	Status     uint64
75 76 77 78 79

	// Information on goroutine location.
	File string
	Line int
	Func *gosym.Func
80 81 82

	// PC of entry to top-most deferred function.
	DeferPC uint64
A
aarzilli 已提交
83 84 85

	// Thread that this goroutine is currently allocated to
	thread *Thread
86 87
}

88 89 90 91 92 93 94
// Scope for variable evaluation
type EvalScope struct {
	Thread *Thread
	PC     uint64
	CFA    int64
}

95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
func newVariable(name string, addr uintptr, dwarfType dwarf.Type, thread *Thread) (*Variable, error) {
	v := &Variable{
		Name:      name,
		Addr:      addr,
		dwarfType: dwarfType,
		thread:    thread,
		Type:      dwarfType.String(),
	}

	switch t := dwarfType.(type) {
	case *dwarf.StructType:
		if strings.HasPrefix(t.StructName, "[]") {
			err := v.loadSliceInfo(t)
			if err != nil {
				return nil, err
			}
		}
	case *dwarf.ArrayType:
		v.base = v.Addr
		v.Len = t.Count
		v.Cap = -1
		v.fieldType = t.Type
		v.stride = 0

		if t.Count > 0 {
			v.stride = t.ByteSize / t.Count
		}
	}

	return v, nil
}

func (v *Variable) toField(field *dwarf.StructField) (*Variable, error) {
	name := ""
	if v.Name != "" {
		name = fmt.Sprintf("%s.%s", v.Name, field.Name)
	}
	return newVariable(name, uintptr(int64(v.Addr)+field.ByteOffset), field.Type, v.thread)
}

135 136 137 138 139 140 141 142 143 144 145 146
func (scope *EvalScope) DwarfReader() *reader.Reader {
	return scope.Thread.dbp.DwarfReader()
}

func (scope *EvalScope) Type(offset dwarf.Offset) (dwarf.Type, error) {
	return scope.Thread.dbp.dwarf.Type(offset)
}

func (scope *EvalScope) PtrSize() int {
	return scope.Thread.dbp.arch.PtrSize()
}

147 148
// Returns whether the goroutine is blocked on
// a channel read operation.
149 150 151 152 153
func (g *G) ChanRecvBlocked() bool {
	return g.WaitReason == ChanRecv
}

// chanRecvReturnAddr returns the address of the return from a channel read.
D
Derek Parker 已提交
154
func (g *G) chanRecvReturnAddr(dbp *Process) (uint64, error) {
155 156 157 158 159
	locs, err := dbp.stacktrace(g.PC, g.SP, 4)
	if err != nil {
		return 0, err
	}
	topLoc := locs[len(locs)-1]
160
	return topLoc.Current.PC, nil
D
Derek Parker 已提交
161 162
}

D
Derek Parker 已提交
163 164
// NoGError returned when a G could not be found
// for a specific thread.
165 166 167 168 169 170 171 172
type NoGError struct {
	tid int
}

func (ng NoGError) Error() string {
	return fmt.Sprintf("no G executing on thread %d", ng.tid)
}

D
Derek Parker 已提交
173
func parseG(thread *Thread, gaddr uint64, deref bool) (*G, error) {
174 175 176 177 178 179 180 181 182 183 184 185 186
	initialInstructions := make([]byte, thread.dbp.arch.PtrSize()+1)
	initialInstructions[0] = op.DW_OP_addr
	binary.LittleEndian.PutUint64(initialInstructions[1:], gaddr)
	if deref {
		gaddrbytes, err := thread.readMemory(uintptr(gaddr), thread.dbp.arch.PtrSize())
		if err != nil {
			return nil, fmt.Errorf("error derefing *G %s", err)
		}
		initialInstructions = append([]byte{op.DW_OP_addr}, gaddrbytes...)
		gaddr = binary.LittleEndian.Uint64(gaddrbytes)
		if gaddr == 0 {
			return nil, NoGError{tid: thread.Id}
		}
187
	}
188

189
	rdr := thread.dbp.DwarfReader()
D
Derek Parker 已提交
190
	rdr.Seek(0)
191
	entry, err := rdr.SeekToTypeNamed("runtime.g")
192 193 194
	if err != nil {
		return nil, err
	}
D
Derek Parker 已提交
195

196 197 198 199 200 201 202
	// Parse defer
	deferAddr, err := rdr.AddrForMember("_defer", initialInstructions)
	if err != nil {
		return nil, err
	}
	var deferPC uint64
	// Dereference *defer pointer
203
	deferAddrBytes, err := thread.readMemory(uintptr(deferAddr), thread.dbp.arch.PtrSize())
204
	if err != nil {
205
		return nil, fmt.Errorf("error derefing defer %s", err)
206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222
	}
	if binary.LittleEndian.Uint64(deferAddrBytes) != 0 {
		initialDeferInstructions := append([]byte{op.DW_OP_addr}, deferAddrBytes...)
		_, err = rdr.SeekToTypeNamed("runtime._defer")
		if err != nil {
			return nil, err
		}
		deferPCAddr, err := rdr.AddrForMember("fn", initialDeferInstructions)
		deferPC, err = thread.readUintRaw(uintptr(deferPCAddr), 8)
		if err != nil {
			return nil, err
		}
		deferPC, err = thread.readUintRaw(uintptr(deferPC), 8)
		if err != nil {
			return nil, err
		}
	}
223 224 225 226 227 228 229 230 231

	// Let's parse all of the members we care about in order so that
	// we don't have to spend any extra time seeking.

	err = rdr.SeekToEntry(entry)
	if err != nil {
		return nil, err
	}

D
Derek Parker 已提交
232 233
	// Parse sched
	schedAddr, err := rdr.AddrForMember("sched", initialInstructions)
234
	if err != nil {
D
Derek Parker 已提交
235
		return nil, err
236
	}
D
Derek Parker 已提交
237 238
	// From sched, let's parse PC and SP.
	sp, err := thread.readUintRaw(uintptr(schedAddr), 8)
239
	if err != nil {
D
Derek Parker 已提交
240
		return nil, err
241
	}
242
	pc, err := thread.readUintRaw(uintptr(schedAddr+uint64(thread.dbp.arch.PtrSize())), 8)
243
	if err != nil {
D
Derek Parker 已提交
244
		return nil, err
245
	}
246 247 248 249 250 251
	// Parse atomicstatus
	atomicStatusAddr, err := rdr.AddrForMember("atomicstatus", initialInstructions)
	if err != nil {
		return nil, err
	}
	atomicStatus, err := thread.readUintRaw(uintptr(atomicStatusAddr), 4)
D
Derek Parker 已提交
252 253
	// Parse goid
	goidAddr, err := rdr.AddrForMember("goid", initialInstructions)
254 255 256
	if err != nil {
		return nil, err
	}
D
Derek Parker 已提交
257
	goid, err := thread.readIntRaw(uintptr(goidAddr), 8)
258 259 260
	if err != nil {
		return nil, err
	}
D
Derek Parker 已提交
261 262
	// Parse waitreason
	waitReasonAddr, err := rdr.AddrForMember("waitreason", initialInstructions)
263
	if err != nil {
D
Derek Parker 已提交
264
		return nil, err
265
	}
D
Derek Parker 已提交
266
	waitreason, err := thread.readString(uintptr(waitReasonAddr))
267
	if err != nil {
D
Derek Parker 已提交
268
		return nil, err
269
	}
D
Derek Parker 已提交
270 271
	// Parse gopc
	gopcAddr, err := rdr.AddrForMember("gopc", initialInstructions)
272
	if err != nil {
D
Derek Parker 已提交
273 274 275 276 277
		return nil, err
	}
	gopc, err := thread.readUintRaw(uintptr(gopcAddr), 8)
	if err != nil {
		return nil, err
278
	}
279

280
	f, l, fn := thread.dbp.goSymTable.PCToLine(pc)
281
	g := &G{
D
Derek Parker 已提交
282 283 284 285
		Id:         int(goid),
		GoPC:       gopc,
		PC:         pc,
		SP:         sp,
286 287 288 289
		File:       f,
		Line:       l,
		Func:       fn,
		WaitReason: waitreason,
290
		DeferPC:    deferPC,
291
		Status:     atomicStatus,
292 293
	}
	return g, nil
294 295
}

296
// Returns information for the named variable.
297 298 299 300 301 302 303 304 305
func (scope *EvalScope) ExtractVariableInfo(name string) (*Variable, error) {
	varName := name
	memberName := ""
	if strings.Contains(name, ".") {
		idx := strings.Index(name, ".")
		varName = name[:idx]
		memberName = name[idx+1:]
	}

306
	v, err := scope.extractVarInfo(varName)
307 308 309 310
	if err != nil {
		origErr := err
		// Attempt to evaluate name as a package variable.
		if memberName != "" {
311
			v, err = scope.packageVarAddr(name)
312 313 314
		} else {
			_, _, fn := scope.Thread.dbp.PCToLine(scope.PC)
			if fn != nil {
315
				v, err = scope.packageVarAddr(fn.PackageName() + "." + name)
316 317 318 319 320
			}
		}
		if err != nil {
			return nil, origErr
		}
321
		v.Name = name
322 323
	} else {
		if len(memberName) > 0 {
324
			v, err = v.structMember(memberName)
325 326 327 328 329
			if err != nil {
				return nil, err
			}
		}
	}
330
	return v, nil
331 332
}

333
// Returns the value of the named variable.
334
func (scope *EvalScope) EvalVariable(name string) (*Variable, error) {
335
	v, err := scope.ExtractVariableInfo(name)
336 337 338
	if err != nil {
		return nil, err
	}
339 340
	err = v.loadValue(true)
	return v, err
341
}
342

343 344 345 346 347 348 349 350 351
// Sets the value of the named variable
func (scope *EvalScope) SetVariable(name, value string) error {
	addr, err := scope.ExtractVariableInfo(name)
	if err != nil {
		return err
	}
	return addr.setValue(value)
}

352 353
func (scope *EvalScope) extractVariableFromEntry(entry *dwarf.Entry) (*Variable, error) {
	rdr := scope.DwarfReader()
354
	v, err := scope.extractVarInfoFromEntry(entry, rdr)
355
	if err != nil {
D
Derek Parker 已提交
356 357
		return nil, err
	}
358 359
	err = v.loadValue(true)
	return v, err
360
}
D
Derek Parker 已提交
361

362 363 364 365 366 367
func (scope *EvalScope) extractVarInfo(varName string) (*Variable, error) {
	reader := scope.DwarfReader()

	_, err := reader.SeekToFunction(scope.PC)
	if err != nil {
		return nil, err
368 369
	}

370
	for entry, err := reader.NextScopeVariable(); entry != nil; entry, err = reader.NextScopeVariable() {
D
Derek Parker 已提交
371
		if err != nil {
372
			return nil, err
D
Derek Parker 已提交
373 374 375 376 377 378 379
		}

		n, ok := entry.Val(dwarf.AttrName).(string)
		if !ok {
			continue
		}

380
		if n == varName {
381
			return scope.extractVarInfoFromEntry(entry, reader)
D
Derek Parker 已提交
382 383
		}
	}
384
	return nil, fmt.Errorf("could not find symbol value for %s", varName)
D
Derek Parker 已提交
385
}
386

387
// LocalVariables returns all local variables from the current function scope.
388 389
func (scope *EvalScope) LocalVariables() ([]*Variable, error) {
	return scope.variablesByTag(dwarf.TagVariable)
390 391 392
}

// FunctionArguments returns the name, value, and type of all current function arguments.
393 394
func (scope *EvalScope) FunctionArguments() ([]*Variable, error) {
	return scope.variablesByTag(dwarf.TagFormalParameter)
395 396 397
}

// PackageVariables returns the name, value, and type of all package variables in the application.
398 399
func (scope *EvalScope) PackageVariables() ([]*Variable, error) {
	reader := scope.DwarfReader()
400 401 402 403 404 405 406 407 408

	vars := make([]*Variable, 0)

	for entry, err := reader.NextPackageVariable(); entry != nil; entry, err = reader.NextPackageVariable() {
		if err != nil {
			return nil, err
		}

		// Ignore errors trying to extract values
409
		val, err := scope.extractVariableFromEntry(entry)
410 411 412 413 414 415 416 417 418
		if err != nil {
			continue
		}
		vars = append(vars, val)
	}

	return vars, nil
}

419 420
func (dbp *Process) EvalPackageVariable(name string) (*Variable, error) {
	scope := &EvalScope{Thread: dbp.CurrentThread, PC: 0, CFA: 0}
421

422
	v, err := scope.packageVarAddr(name)
423 424 425
	if err != nil {
		return nil, err
	}
426 427
	err = v.loadValue(true)
	return v, err
428 429 430 431
}

func (scope *EvalScope) packageVarAddr(name string) (*Variable, error) {
	reader := scope.DwarfReader()
432 433 434 435 436 437 438 439 440 441 442
	for entry, err := reader.NextPackageVariable(); entry != nil; entry, err = reader.NextPackageVariable() {
		if err != nil {
			return nil, err
		}

		n, ok := entry.Val(dwarf.AttrName).(string)
		if !ok {
			continue
		}

		if n == name {
443
			return scope.extractVarInfoFromEntry(entry, reader)
444 445 446 447 448
		}
	}
	return nil, fmt.Errorf("could not find symbol value for %s", name)
}

449 450 451
func (v *Variable) structMember(memberName string) (*Variable, error) {
	structVar, err := v.maybeDereference()
	structVar.Name = v.Name
452 453 454
	if err != nil {
		return nil, err
	}
455
	structVar = structVar.resolveTypedefs()
456

457 458 459 460 461
	switch t := structVar.dwarfType.(type) {
	case *dwarf.StructType:
		for _, field := range t.Field {
			if field.Name != memberName {
				continue
462
			}
463 464
			if structVar.Addr == 0 {
				return nil, fmt.Errorf("%s is nil", v.Name)
465
			}
466
			return structVar.toField(field)
467
		}
468 469 470
		return nil, fmt.Errorf("%s has no member %s", v.Name, memberName)
	default:
		return nil, fmt.Errorf("%s type %s is not a struct", v.Name, structVar.dwarfType)
471
	}
472 473
}

474 475 476
// Extracts the name and type of a variable from a dwarf entry
// then executes the instructions given in the  DW_AT_location attribute to grab the variable's address
func (scope *EvalScope) extractVarInfoFromEntry(entry *dwarf.Entry, rdr *reader.Reader) (*Variable, error) {
E
epipho 已提交
477
	if entry == nil {
D
Derek Parker 已提交
478
		return nil, fmt.Errorf("invalid entry")
E
epipho 已提交
479 480 481 482 483 484 485 486
	}

	if entry.Tag != dwarf.TagFormalParameter && entry.Tag != dwarf.TagVariable {
		return nil, fmt.Errorf("invalid entry tag, only supports FormalParameter and Variable, got %s", entry.Tag.String())
	}

	n, ok := entry.Val(dwarf.AttrName).(string)
	if !ok {
D
Derek Parker 已提交
487
		return nil, fmt.Errorf("type assertion failed")
E
epipho 已提交
488 489 490 491
	}

	offset, ok := entry.Val(dwarf.AttrType).(dwarf.Offset)
	if !ok {
D
Derek Parker 已提交
492
		return nil, fmt.Errorf("type assertion failed")
E
epipho 已提交
493 494
	}

495
	t, err := scope.Type(offset)
E
epipho 已提交
496 497 498 499 500 501
	if err != nil {
		return nil, err
	}

	instructions, ok := entry.Val(dwarf.AttrLocation).([]byte)
	if !ok {
D
Derek Parker 已提交
502
		return nil, fmt.Errorf("type assertion failed")
E
epipho 已提交
503 504
	}

505
	addr, err := op.ExecuteStackProgram(scope.CFA, instructions)
E
epipho 已提交
506 507 508 509
	if err != nil {
		return nil, err
	}

510
	return newVariable(n, uintptr(addr), t, scope.Thread)
E
epipho 已提交
511 512
}

513
// If v is a pointer a new variable is returned containing the value pointed by v.
514 515
func (v *Variable) maybeDereference() (*Variable, error) {
	v = v.resolveTypedefs()
516

517 518 519
	switch t := v.dwarfType.(type) {
	case *dwarf.PtrType:
		ptrval, err := v.thread.readUintRaw(uintptr(v.Addr), int64(v.thread.dbp.arch.PtrSize()))
520
		if err != nil {
521
			return nil, err
522 523
		}

524 525 526
		return newVariable("", uintptr(ptrval), t.Type, v.thread)
	default:
		return v, nil
527 528
	}
}
529

530
// Returns a Variable with the same address but a concrete dwarfType.
531 532
func (v *Variable) resolveTypedefs() *Variable {
	typ := v.dwarfType
533 534 535 536 537 538
	for {
		if tt, ok := typ.(*dwarf.TypedefType); ok {
			typ = tt.Type
		} else {
			break
		}
539
	}
540 541 542 543 544
	r := *v
	r.dwarfType = typ
	return &r
}

545
// Extracts the value of the variable at the given address.
546 547 548 549 550 551 552
func (v *Variable) loadValue(printStructName bool) (err error) {
	v.Value, err = v.loadValueInternal(printStructName, 0)
	return
}

func (v *Variable) loadValueInternal(printStructName bool, recurseLevel int) (string, error) {
	v = v.resolveTypedefs()
553

554
	switch t := v.dwarfType.(type) {
555
	case *dwarf.PtrType:
556
		ptrv, err := v.maybeDereference()
557 558 559
		if err != nil {
			return "", err
		}
560

561
		if ptrv.Addr == 0 {
562 563 564
			return fmt.Sprintf("%s nil", t.String()), nil
		}

565
		// Don't increase the recursion level when dereferencing pointers
566
		val, err := ptrv.loadValueInternal(printStructName, recurseLevel)
567 568 569 570
		if err != nil {
			return "", err
		}

571
		return fmt.Sprintf("*%s", val), nil
572
	case *dwarf.StructType:
E
epipho 已提交
573 574
		switch {
		case t.StructName == "string":
575
			return v.thread.readString(uintptr(v.Addr))
E
epipho 已提交
576
		case strings.HasPrefix(t.StructName, "[]"):
577
			return v.loadArrayValues(recurseLevel)
578
		default:
D
Derek Parker 已提交
579
			// Recursively call extractValue to grab
580
			// the value of all the members of the struct.
581
			if recurseLevel <= maxVariableRecurse {
582
				errcount := 0
583
				fields := make([]string, 0, len(t.Field))
584
				for i, field := range t.Field {
585 586 587 588 589
					var (
						err      error
						val      string
						fieldvar *Variable
					)
590 591 592 593 594

					fieldvar, err = v.toField(field)
					if err == nil {
						val, err = fieldvar.loadValueInternal(printStructName, recurseLevel+1)
					}
595
					if err != nil {
596 597
						errcount++
						val = fmt.Sprintf("<unreadable: %s>", err.Error())
598 599 600
					}

					fields = append(fields, fmt.Sprintf("%s: %s", field.Name, val))
601 602 603 604

					if errcount > maxErrCount {
						fields = append(fields, fmt.Sprintf("...+%d more", len(t.Field)-i))
					}
605
				}
606 607 608 609
				if printStructName {
					return fmt.Sprintf("%s {%s}", t.StructName, strings.Join(fields, ", ")), nil
				}
				return fmt.Sprintf("{%s}", strings.Join(fields, ", ")), nil
610
			}
611
			// no fields
E
epipho 已提交
612
			if printStructName {
613
				return fmt.Sprintf("%s {...}", t.StructName), nil
E
epipho 已提交
614
			}
615
			return "{...}", nil
616 617
		}
	case *dwarf.ArrayType:
618
		return v.loadArrayValues(recurseLevel)
619
	case *dwarf.ComplexType:
620
		return v.readComplex(t.ByteSize)
621
	case *dwarf.IntType:
622
		return v.readInt(t.ByteSize)
E
epipho 已提交
623
	case *dwarf.UintType:
624
		return v.readUint(t.ByteSize)
625
	case *dwarf.FloatType:
626
		return v.readFloat(t.ByteSize)
E
epipho 已提交
627
	case *dwarf.BoolType:
628
		return v.readBool()
629
	case *dwarf.FuncType:
630
		return v.readFunctionPtr()
631 632 633 634
	case *dwarf.VoidType:
		return "(void)", nil
	case *dwarf.UnspecifiedType:
		return "(unknown)", nil
635 636
	default:
		fmt.Printf("Unknown type: %T\n", t)
637 638
	}

639
	return "", fmt.Errorf("could not find value for type %s", v.dwarfType)
640 641
}

642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662
func (v *Variable) setValue(value string) error {
	v = v.resolveTypedefs()

	switch t := v.dwarfType.(type) {
	case *dwarf.PtrType:
		return v.writeUint(false, value, int64(v.thread.dbp.arch.PtrSize()))
	case *dwarf.ComplexType:
		return v.writeComplex(value, t.ByteSize)
	case *dwarf.IntType:
		return v.writeUint(true, value, t.ByteSize)
	case *dwarf.UintType:
		return v.writeUint(false, value, t.ByteSize)
	case *dwarf.FloatType:
		return v.writeFloat(value, t.ByteSize)
	case *dwarf.BoolType:
		return v.writeBool(value)
	default:
		return fmt.Errorf("Can not set value of variables of type: %T\n", t)
	}
}

D
Derek Parker 已提交
663
func (thread *Thread) readString(addr uintptr) (string, error) {
664 665 666 667
	// string data structure is always two ptrs in size. Addr, followed by len
	// http://research.swtch.com/godata

	// read len
668
	val, err := thread.readMemory(addr+uintptr(thread.dbp.arch.PtrSize()), thread.dbp.arch.PtrSize())
669
	if err != nil {
670
		return "", fmt.Errorf("could not read string len %s", err)
671
	}
672
	strlen := int(binary.LittleEndian.Uint64(val))
673 674 675 676 677 678 679 680
	if strlen < 0 {
		return "", fmt.Errorf("invalid length: %d", strlen)
	}

	count := strlen
	if count > maxArrayValues {
		count = maxArrayValues
	}
681 682

	// read addr
683
	val, err = thread.readMemory(addr, thread.dbp.arch.PtrSize())
684
	if err != nil {
685
		return "", fmt.Errorf("could not read string pointer %s", err)
686 687
	}
	addr = uintptr(binary.LittleEndian.Uint64(val))
D
Derek Parker 已提交
688 689 690
	if addr == 0 {
		return "", nil
	}
D
Derek Parker 已提交
691

692
	val, err = thread.readMemory(addr, count)
693
	if err != nil {
694
		return "", fmt.Errorf("could not read string at %#v due to %s", addr, err)
695 696
	}

697 698 699 700 701 702 703
	retstr := *(*string)(unsafe.Pointer(&val))

	if count != strlen {
		retstr = retstr + fmt.Sprintf("...+%d more", strlen-count)
	}

	return retstr, nil
704 705
}

706 707
func (v *Variable) loadSliceInfo(t *dwarf.StructType) error {
	var err error
E
epipho 已提交
708 709 710
	for _, f := range t.Field {
		switch f.Name {
		case "array":
711 712 713 714 715 716 717 718 719 720
			var base uint64
			base, err = v.thread.readUintRaw(uintptr(int64(v.Addr)+f.ByteOffset), int64(v.thread.dbp.arch.PtrSize()))
			if err == nil {
				v.base = uintptr(base)
				// Dereference array type to get value type
				ptrType, ok := f.Type.(*dwarf.PtrType)
				if !ok {
					return fmt.Errorf("Invalid type %s in slice array", f.Type)
				}
				v.fieldType = ptrType.Type
E
epipho 已提交
721 722
			}
		case "len":
723 724 725
			lstrAddr, err := v.toField(f)
			if err == nil {
				err = lstrAddr.loadValue(true)
E
epipho 已提交
726
			}
727 728
			if err == nil {
				v.Len, err = strconv.ParseInt(lstrAddr.Value, 10, 64)
E
epipho 已提交
729 730
			}
		case "cap":
731 732 733
			cstrAddr, err := v.toField(f)
			if err == nil {
				err = cstrAddr.loadValue(true)
E
epipho 已提交
734
			}
735 736
			if err == nil {
				v.Cap, err = strconv.ParseInt(cstrAddr.Value, 10, 64)
E
epipho 已提交
737 738 739 740
			}
		}
	}

741
	if err != nil {
742
		return nil
743 744
	}

745 746 747
	v.stride = v.fieldType.Size()
	if _, ok := v.fieldType.(*dwarf.PtrType); ok {
		v.stride = int64(v.thread.dbp.arch.PtrSize())
748
	}
749 750

	return nil
751 752
}

753
func (v *Variable) loadArrayValues(recurseLevel int) (string, error) {
E
epipho 已提交
754
	vals := make([]string, 0)
755
	errcount := 0
756

757
	for i := int64(0); i < v.Len; i++ {
758 759
		// Cap number of elements
		if i >= maxArrayValues {
760
			vals = append(vals, fmt.Sprintf("...+%d more", v.Len-maxArrayValues))
761 762 763
			break
		}

764 765 766 767 768
		var val string
		fieldvar, err := newVariable("", uintptr(int64(v.base)+(i*v.stride)), v.fieldType, v.thread)
		if err == nil {
			val, err = fieldvar.loadValueInternal(false, recurseLevel+1)
		}
E
epipho 已提交
769
		if err != nil {
770 771
			errcount++
			val = fmt.Sprintf("<unreadable: %s>", err.Error())
E
epipho 已提交
772
		}
773

E
epipho 已提交
774
		vals = append(vals, val)
775
		if errcount > maxErrCount {
776
			vals = append(vals, fmt.Sprintf("...+%d more", v.Len-i))
777 778
			break
		}
779
	}
780 781 782 783 784 785

	if v.Cap < 0 {
		return fmt.Sprintf("%s [%s]", v.dwarfType, strings.Join(vals, ",")), nil
	} else {
		return fmt.Sprintf("[]%s len: %d, cap: %d, [%s]", v.fieldType, v.Len, v.Cap, strings.Join(vals, ",")), nil
	}
786 787
}

788
func (v *Variable) readComplex(size int64) (string, error) {
789 790 791 792 793 794 795 796 797
	var fs int64
	switch size {
	case 8:
		fs = 4
	case 16:
		fs = 8
	default:
		return "", fmt.Errorf("invalid size (%d) for complex type", size)
	}
798
	r, err := v.readFloat(fs)
799 800 801
	if err != nil {
		return "", err
	}
802 803 804
	imagvar := *v
	imagvar.Addr += uintptr(fs)
	i, err := imagvar.readFloat(fs)
805 806 807
	if err != nil {
		return "", err
	}
808
	return fmt.Sprintf("(%s + %si)", r, i), nil
809 810
}

811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885
func (v *Variable) writeComplex(value string, size int64) error {
	var real, imag float64

	expr, err := parser.ParseExpr(value)
	if err != nil {
		return err
	}

	var lits []*ast.BasicLit

	if e, ok := expr.(*ast.ParenExpr); ok {
		expr = e.X
	}

	switch e := expr.(type) {
	case *ast.BinaryExpr: // "<float> + <float>i" or "<float>i + <float>"
		x, xok := e.X.(*ast.BasicLit)
		y, yok := e.Y.(*ast.BasicLit)
		if e.Op != token.ADD || !xok || !yok {
			return fmt.Errorf("Not a complex constant: %s", value)
		}
		lits = []*ast.BasicLit{x, y}
	case *ast.CallExpr: // "complex(<float>, <float>)"
		tname, ok := e.Fun.(*ast.Ident)
		if !ok {
			return fmt.Errorf("Not a complex constant: %s", value)
		}
		if (tname.Name != "complex64") && (tname.Name != "complex128") {
			return fmt.Errorf("Not a complex constant: %s", value)
		}
		if len(e.Args) != 2 {
			return fmt.Errorf("Not a complex constant: %s", value)
		}
		for i := range e.Args {
			lit, ok := e.Args[i].(*ast.BasicLit)
			if !ok {
				return fmt.Errorf("Not a complex constant: %s", value)
			}
			lits = append(lits, lit)
		}
		lits[1].Kind = token.IMAG
		lits[1].Value = lits[1].Value + "i"
	case *ast.BasicLit: // "<float>" or "<float>i"
		lits = []*ast.BasicLit{e}
	default:
		return fmt.Errorf("Not a complex constant: %s", value)
	}

	for _, lit := range lits {
		var err error
		var v float64
		switch lit.Kind {
		case token.FLOAT, token.INT:
			v, err = strconv.ParseFloat(lit.Value, int(size/2))
			real += v
		case token.IMAG:
			v, err = strconv.ParseFloat(lit.Value[:len(lit.Value)-1], int(size/2))
			imag += v
		default:
			return fmt.Errorf("Not a complex constant: %s", value)
		}
		if err != nil {
			return err
		}
	}

	err = v.writeFloatRaw(real, int64(size/2))
	if err != nil {
		return err
	}
	imagaddr := *v
	imagaddr.Addr += uintptr(size / 2)
	return imagaddr.writeFloatRaw(imag, int64(size/2))
}

886 887
func (v *Variable) readInt(size int64) (string, error) {
	n, err := v.thread.readIntRaw(v.Addr, size)
D
Derek Parker 已提交
888 889 890 891 892 893
	if err != nil {
		return "", err
	}
	return strconv.FormatInt(n, 10), nil
}

D
Derek Parker 已提交
894
func (thread *Thread) readIntRaw(addr uintptr, size int64) (int64, error) {
E
epipho 已提交
895
	var n int64
896

897
	val, err := thread.readMemory(addr, int(size))
898
	if err != nil {
D
Derek Parker 已提交
899
		return 0, err
900 901
	}

902 903
	switch size {
	case 1:
E
epipho 已提交
904
		n = int64(val[0])
905
	case 2:
E
epipho 已提交
906
		n = int64(binary.LittleEndian.Uint16(val))
907
	case 4:
E
epipho 已提交
908
		n = int64(binary.LittleEndian.Uint32(val))
909
	case 8:
E
epipho 已提交
910
		n = int64(binary.LittleEndian.Uint64(val))
911
	}
912

D
Derek Parker 已提交
913
	return n, nil
E
epipho 已提交
914 915
}

916 917
func (v *Variable) readUint(size int64) (string, error) {
	n, err := v.thread.readUintRaw(v.Addr, size)
D
Derek Parker 已提交
918 919 920 921 922 923
	if err != nil {
		return "", err
	}
	return strconv.FormatUint(n, 10), nil
}

924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954
func (v *Variable) writeUint(signed bool, value string, size int64) error {
	var n uint64
	var err error
	if signed {
		var m int64
		m, err = strconv.ParseInt(value, 0, int(size*8))
		n = uint64(m)
	} else {
		n, err = strconv.ParseUint(value, 0, int(size*8))
	}
	if err != nil {
		return err
	}

	val := make([]byte, size)

	switch size {
	case 1:
		val[0] = byte(n)
	case 2:
		binary.LittleEndian.PutUint16(val, uint16(n))
	case 4:
		binary.LittleEndian.PutUint32(val, uint32(n))
	case 8:
		binary.LittleEndian.PutUint64(val, uint64(n))
	}

	_, err = v.thread.writeMemory(v.Addr, val)
	return err
}

D
Derek Parker 已提交
955
func (thread *Thread) readUintRaw(addr uintptr, size int64) (uint64, error) {
E
epipho 已提交
956 957
	var n uint64

958
	val, err := thread.readMemory(addr, int(size))
E
epipho 已提交
959
	if err != nil {
D
Derek Parker 已提交
960
		return 0, err
E
epipho 已提交
961 962 963 964 965 966 967 968 969 970 971 972 973
	}

	switch size {
	case 1:
		n = uint64(val[0])
	case 2:
		n = uint64(binary.LittleEndian.Uint16(val))
	case 4:
		n = uint64(binary.LittleEndian.Uint32(val))
	case 8:
		n = uint64(binary.LittleEndian.Uint64(val))
	}

D
Derek Parker 已提交
974
	return n, nil
975 976
}

977 978
func (v *Variable) readFloat(size int64) (string, error) {
	val, err := v.thread.readMemory(v.Addr, int(size))
979 980 981 982 983
	if err != nil {
		return "", err
	}
	buf := bytes.NewBuffer(val)

D
Derek Parker 已提交
984 985 986 987 988 989 990 991 992 993 994
	switch size {
	case 4:
		n := float32(0)
		binary.Read(buf, binary.LittleEndian, &n)
		return strconv.FormatFloat(float64(n), 'f', -1, int(size)*8), nil
	case 8:
		n := float64(0)
		binary.Read(buf, binary.LittleEndian, &n)
		return strconv.FormatFloat(n, 'f', -1, int(size)*8), nil
	}

D
Derek Parker 已提交
995
	return "", fmt.Errorf("could not read float")
996 997
}

998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021
func (v *Variable) writeFloat(value string, size int64) error {
	f, err := strconv.ParseFloat(value, int(size*8))
	if err != nil {
		return err
	}
	return v.writeFloatRaw(f, size)
}

func (v *Variable) writeFloatRaw(f float64, size int64) error {
	buf := bytes.NewBuffer(make([]byte, 0, size))

	switch size {
	case 4:
		n := float32(f)
		binary.Write(buf, binary.LittleEndian, n)
	case 8:
		n := float64(f)
		binary.Write(buf, binary.LittleEndian, n)
	}

	_, err := v.thread.writeMemory(v.Addr, buf.Bytes())
	return err
}

1022 1023
func (v *Variable) readBool() (string, error) {
	val, err := v.thread.readMemory(v.Addr, 1)
E
epipho 已提交
1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034
	if err != nil {
		return "", err
	}

	if val[0] == 0 {
		return "false", nil
	}

	return "true", nil
}

1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047
func (v *Variable) writeBool(value string) error {
	b, err := strconv.ParseBool(value)
	if err != nil {
		return err
	}
	val := []byte{0}
	if b {
		val[0] = *(*byte)(unsafe.Pointer(&b))
	}
	_, err = v.thread.writeMemory(v.Addr, val)
	return err
}

1048 1049
func (v *Variable) readFunctionPtr() (string, error) {
	val, err := v.thread.readMemory(v.Addr, v.thread.dbp.arch.PtrSize())
1050 1051 1052 1053 1054
	if err != nil {
		return "", err
	}

	// dereference pointer to find function pc
1055 1056
	fnaddr := uintptr(binary.LittleEndian.Uint64(val))
	if fnaddr == 0 {
1057 1058
		return "nil", nil
	}
1059

1060
	val, err = v.thread.readMemory(fnaddr, v.thread.dbp.arch.PtrSize())
1061 1062 1063 1064 1065
	if err != nil {
		return "", err
	}

	funcAddr := binary.LittleEndian.Uint64(val)
1066
	fn := v.thread.dbp.goSymTable.PCToFunc(uint64(funcAddr))
1067 1068
	if fn == nil {
		return "", fmt.Errorf("could not find function for %#v", funcAddr)
1069 1070
	}

1071
	return fn.Name, nil
1072 1073
}

E
epipho 已提交
1074
// Fetches all variables of a specific type in the current function scope
1075 1076
func (scope *EvalScope) variablesByTag(tag dwarf.Tag) ([]*Variable, error) {
	reader := scope.DwarfReader()
E
epipho 已提交
1077

1078
	_, err := reader.SeekToFunction(scope.PC)
1079
	if err != nil {
E
epipho 已提交
1080 1081 1082 1083 1084
		return nil, err
	}

	vars := make([]*Variable, 0)

1085
	for entry, err := reader.NextScopeVariable(); entry != nil; entry, err = reader.NextScopeVariable() {
E
epipho 已提交
1086 1087 1088 1089 1090
		if err != nil {
			return nil, err
		}

		if entry.Tag == tag {
1091
			val, err := scope.extractVariableFromEntry(entry)
E
epipho 已提交
1092
			if err != nil {
E
epipho 已提交
1093 1094
				// skip variables that we can't parse yet
				continue
E
epipho 已提交
1095 1096 1097 1098 1099 1100 1101 1102
			}

			vars = append(vars, val)
		}
	}

	return vars, nil
}