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

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

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

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

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

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

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

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

52 53 54 55 56 57 58 59 60 61 62 63 64
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
)

65 66
// Represents a runtime G (goroutine) structure (at least the
// fields that Delve is interested in).
D
Derek Parker 已提交
67
type G struct {
68 69 70 71 72
	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.
73
	Status     uint64
74

75 76
	// Information on goroutine location
	Current Location
77 78 79

	// PC of entry to top-most deferred function.
	DeferPC uint64
A
aarzilli 已提交
80 81 82

	// Thread that this goroutine is currently allocated to
	thread *Thread
83 84

	dbp *Process
85 86
}

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

94 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
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) {
D
Derek Parker 已提交
127 128 129 130
	if v.Addr == 0 {
		return nil, fmt.Errorf("%s is nil", v.Name)
	}

131 132
	name := ""
	if v.Name != "" {
133 134 135 136
		parts := strings.Split(field.Name, ".")
		if len(parts) > 1 {
			name = fmt.Sprintf("%s.%s", v.Name, parts[1])
		} else {
D
Derek Parker 已提交
137
			name = fmt.Sprintf("%s.%s", v.Name, field.Name)
138
		}
139 140 141 142
	}
	return newVariable(name, uintptr(int64(v.Addr)+field.ByteOffset), field.Type, v.thread)
}

143 144 145 146 147 148 149 150 151 152 153 154
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()
}

155 156
// Returns whether the goroutine is blocked on
// a channel read operation.
157 158 159 160 161
func (g *G) ChanRecvBlocked() bool {
	return g.WaitReason == ChanRecv
}

// chanRecvReturnAddr returns the address of the return from a channel read.
D
Derek Parker 已提交
162
func (g *G) chanRecvReturnAddr(dbp *Process) (uint64, error) {
163
	locs, err := dbp.GoroutineStacktrace(g, 4)
164 165 166 167
	if err != nil {
		return 0, err
	}
	topLoc := locs[len(locs)-1]
168
	return topLoc.Current.PC, nil
D
Derek Parker 已提交
169 170
}

D
Derek Parker 已提交
171 172
// NoGError returned when a G could not be found
// for a specific thread.
173 174 175 176 177 178 179 180
type NoGError struct {
	tid int
}

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

D
Derek Parker 已提交
181
func parseG(thread *Thread, gaddr uint64, deref bool) (*G, error) {
182 183 184 185 186 187 188 189 190 191 192 193 194
	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}
		}
195
	}
196

197
	rdr := thread.dbp.DwarfReader()
D
Derek Parker 已提交
198
	rdr.Seek(0)
199
	entry, err := rdr.SeekToTypeNamed("runtime.g")
200 201 202
	if err != nil {
		return nil, err
	}
D
Derek Parker 已提交
203

204 205 206 207 208 209 210
	// Parse defer
	deferAddr, err := rdr.AddrForMember("_defer", initialInstructions)
	if err != nil {
		return nil, err
	}
	var deferPC uint64
	// Dereference *defer pointer
211
	deferAddrBytes, err := thread.readMemory(uintptr(deferAddr), thread.dbp.arch.PtrSize())
212
	if err != nil {
213
		return nil, fmt.Errorf("error derefing defer %s", err)
214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230
	}
	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
		}
	}
231 232 233 234 235 236 237 238 239

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

288
	f, l, fn := thread.dbp.goSymTable.PCToLine(pc)
289
	g := &G{
D
Derek Parker 已提交
290 291 292 293
		Id:         int(goid),
		GoPC:       gopc,
		PC:         pc,
		SP:         sp,
294
		Current:    Location{PC: pc, File: f, Line: l, Fn: fn},
295
		WaitReason: waitreason,
296
		DeferPC:    deferPC,
297
		Status:     atomicStatus,
298
		dbp:        thread.dbp,
299 300
	}
	return g, nil
301 302
}

303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335
// From $GOROOT/src/runtime/traceback.go:597
// isExportedRuntime reports whether name is an exported runtime function.
// It is only for runtime functions, so ASCII A-Z is fine.
func isExportedRuntime(name string) bool {
	const n = len("runtime.")
	return len(name) > n && name[:n] == "runtime." && 'A' <= name[n] && name[n] <= 'Z'
}

func (g *G) UserCurrent() Location {
	pc, sp := g.PC, g.SP
	if g.thread != nil {
		regs, err := g.thread.Registers()
		if err != nil {
			return g.Current
		}
		pc, sp = regs.PC(), regs.SP()
	}
	it := newStackIterator(g.dbp, pc, sp)
	for it.Next() {
		frame := it.Frame()
		name := frame.Call.Fn.Name
		if (strings.Index(name, ".") >= 0) && (!strings.HasPrefix(name, "runtime.") || isExportedRuntime(name)) {
			return frame.Call
		}
	}
	return g.Current
}

func (g *G) Go() Location {
	f, l, fn := g.dbp.goSymTable.PCToLine(g.GoPC)
	return Location{PC: g.GoPC, File: f, Line: l, Fn: fn}
}

336
// Returns information for the named variable.
337
func (scope *EvalScope) ExtractVariableInfo(name string) (*Variable, error) {
338 339 340
	parts := strings.Split(name, ".")
	varName := parts[0]
	memberNames := parts[1:]
341

342
	v, err := scope.extractVarInfo(varName)
343 344 345
	if err != nil {
		origErr := err
		// Attempt to evaluate name as a package variable.
346
		if len(memberNames) > 0 {
347
			v, err = scope.packageVarAddr(name)
348 349 350
		} else {
			_, _, fn := scope.Thread.dbp.PCToLine(scope.PC)
			if fn != nil {
351
				v, err = scope.packageVarAddr(fn.PackageName() + "." + name)
352 353 354 355 356
			}
		}
		if err != nil {
			return nil, origErr
		}
357
		v.Name = name
358
	} else {
359
		for _, memberName := range memberNames {
360
			v, err = v.structMember(memberName)
361 362 363 364 365
			if err != nil {
				return nil, err
			}
		}
	}
366
	return v, nil
367 368
}

369
// Returns the value of the named variable.
370
func (scope *EvalScope) EvalVariable(name string) (*Variable, error) {
371
	v, err := scope.ExtractVariableInfo(name)
372 373 374
	if err != nil {
		return nil, err
	}
375 376
	err = v.loadValue(true)
	return v, err
377
}
378

379 380
// Sets the value of the named variable
func (scope *EvalScope) SetVariable(name, value string) error {
381
	v, err := scope.ExtractVariableInfo(name)
382 383 384
	if err != nil {
		return err
	}
385
	return v.setValue(value)
386 387
}

388 389
func (scope *EvalScope) extractVariableFromEntry(entry *dwarf.Entry) (*Variable, error) {
	rdr := scope.DwarfReader()
390
	v, err := scope.extractVarInfoFromEntry(entry, rdr)
391
	if err != nil {
D
Derek Parker 已提交
392 393
		return nil, err
	}
394 395
	err = v.loadValue(true)
	return v, err
396
}
D
Derek Parker 已提交
397

398 399 400 401 402 403
func (scope *EvalScope) extractVarInfo(varName string) (*Variable, error) {
	reader := scope.DwarfReader()

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

406
	for entry, err := reader.NextScopeVariable(); entry != nil; entry, err = reader.NextScopeVariable() {
D
Derek Parker 已提交
407
		if err != nil {
408
			return nil, err
D
Derek Parker 已提交
409 410 411 412 413 414 415
		}

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

416
		if n == varName {
417
			return scope.extractVarInfoFromEntry(entry, reader)
D
Derek Parker 已提交
418 419
		}
	}
420
	return nil, fmt.Errorf("could not find symbol value for %s", varName)
D
Derek Parker 已提交
421
}
422

423
// LocalVariables returns all local variables from the current function scope.
424 425
func (scope *EvalScope) LocalVariables() ([]*Variable, error) {
	return scope.variablesByTag(dwarf.TagVariable)
426 427 428
}

// FunctionArguments returns the name, value, and type of all current function arguments.
429 430
func (scope *EvalScope) FunctionArguments() ([]*Variable, error) {
	return scope.variablesByTag(dwarf.TagFormalParameter)
431 432 433
}

// PackageVariables returns the name, value, and type of all package variables in the application.
434 435
func (scope *EvalScope) PackageVariables() ([]*Variable, error) {
	reader := scope.DwarfReader()
436 437 438 439 440 441 442 443 444

	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
445
		val, err := scope.extractVariableFromEntry(entry)
446 447 448 449 450 451 452 453 454
		if err != nil {
			continue
		}
		vars = append(vars, val)
	}

	return vars, nil
}

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

458
	v, err := scope.packageVarAddr(name)
459 460 461
	if err != nil {
		return nil, err
	}
462 463
	err = v.loadValue(true)
	return v, err
464 465 466 467
}

func (scope *EvalScope) packageVarAddr(name string) (*Variable, error) {
	reader := scope.DwarfReader()
468 469 470 471 472 473 474 475 476 477 478
	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 {
479
			return scope.extractVarInfoFromEntry(entry, reader)
480 481 482 483 484
		}
	}
	return nil, fmt.Errorf("could not find symbol value for %s", name)
}

485 486 487
func (v *Variable) structMember(memberName string) (*Variable, error) {
	structVar, err := v.maybeDereference()
	structVar.Name = v.Name
488 489 490
	if err != nil {
		return nil, err
	}
491 492 493 494 495 496
	structVar = structVar.resolveTypedefs()
	switch t := structVar.dwarfType.(type) {
	case *dwarf.StructType:
		for _, field := range t.Field {
			if field.Name != memberName {
				continue
497
			}
L
Luke Hoban 已提交
498
			return structVar.toField(field)
499 500 501 502 503 504
		}
		// Check for embedded field only if field was
		// not a regular struct member
		for _, field := range t.Field {
			isEmbeddedStructMember :=
				(field.Type.String() == ("struct " + field.Name)) ||
D
Derek Parker 已提交
505 506 507
					(len(field.Name) > 1 &&
						field.Name[0] == '*' &&
						field.Type.String()[1:] == ("struct "+field.Name[1:]))
508 509 510 511 512 513
			if !isEmbeddedStructMember {
				continue
			}
			// Check for embedded field referenced by type name
			parts := strings.Split(field.Name, ".")
			if len(parts) > 1 && parts[1] == memberName {
L
Luke Hoban 已提交
514
				embeddedVar, err := structVar.toField(field)
515 516 517 518 519 520
				if err != nil {
					return nil, err
				}
				return embeddedVar, nil
			}
			// Recursively check for promoted fields on the embedded field
L
Luke Hoban 已提交
521
			embeddedVar, err := structVar.toField(field)
522 523 524 525 526 527 528
			if err != nil {
				return nil, err
			}
			embeddedVar.Name = structVar.Name
			embeddedField, err := embeddedVar.structMember(memberName)
			if embeddedField != nil {
				return embeddedField, nil
529 530
			}
		}
531 532 533
		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)
534
	}
535 536
}

537 538 539
// 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 已提交
540
	if entry == nil {
D
Derek Parker 已提交
541
		return nil, fmt.Errorf("invalid entry")
E
epipho 已提交
542 543 544 545 546 547 548 549
	}

	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 已提交
550
		return nil, fmt.Errorf("type assertion failed")
E
epipho 已提交
551 552 553 554
	}

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

558
	t, err := scope.Type(offset)
E
epipho 已提交
559 560 561 562 563 564
	if err != nil {
		return nil, err
	}

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

568
	addr, err := op.ExecuteStackProgram(scope.CFA, instructions)
E
epipho 已提交
569 570 571 572
	if err != nil {
		return nil, err
	}

573
	return newVariable(n, uintptr(addr), t, scope.Thread)
E
epipho 已提交
574 575
}

576
// If v is a pointer a new variable is returned containing the value pointed by v.
577 578
func (v *Variable) maybeDereference() (*Variable, error) {
	v = v.resolveTypedefs()
579

580 581 582
	switch t := v.dwarfType.(type) {
	case *dwarf.PtrType:
		ptrval, err := v.thread.readUintRaw(uintptr(v.Addr), int64(v.thread.dbp.arch.PtrSize()))
583
		if err != nil {
584
			return nil, err
585 586
		}

587 588 589
		return newVariable("", uintptr(ptrval), t.Type, v.thread)
	default:
		return v, nil
590 591
	}
}
592

593
// Returns a Variable with the same address but a concrete dwarfType.
594 595
func (v *Variable) resolveTypedefs() *Variable {
	typ := v.dwarfType
596 597 598 599 600 601
	for {
		if tt, ok := typ.(*dwarf.TypedefType); ok {
			typ = tt.Type
		} else {
			break
		}
602
	}
603 604 605 606 607
	r := *v
	r.dwarfType = typ
	return &r
}

608
// Extracts the value of the variable at the given address.
609 610 611 612 613 614 615
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()
616

617
	switch t := v.dwarfType.(type) {
618
	case *dwarf.PtrType:
619
		ptrv, err := v.maybeDereference()
620 621 622
		if err != nil {
			return "", err
		}
623

624
		if ptrv.Addr == 0 {
625 626 627
			return fmt.Sprintf("%s nil", t.String()), nil
		}

628
		// Don't increase the recursion level when dereferencing pointers
629
		val, err := ptrv.loadValueInternal(printStructName, recurseLevel)
630 631 632 633
		if err != nil {
			return "", err
		}

634
		return fmt.Sprintf("*%s", val), nil
635
	case *dwarf.StructType:
E
epipho 已提交
636 637
		switch {
		case t.StructName == "string":
638
			return v.thread.readString(uintptr(v.Addr))
E
epipho 已提交
639
		case strings.HasPrefix(t.StructName, "[]"):
640
			return v.loadArrayValues(recurseLevel)
641
		default:
D
Derek Parker 已提交
642
			// Recursively call extractValue to grab
643
			// the value of all the members of the struct.
644
			if recurseLevel <= maxVariableRecurse {
645
				errcount := 0
646
				fields := make([]string, 0, len(t.Field))
647
				for i, field := range t.Field {
648 649 650 651 652
					var (
						err      error
						val      string
						fieldvar *Variable
					)
653 654 655 656 657

					fieldvar, err = v.toField(field)
					if err == nil {
						val, err = fieldvar.loadValueInternal(printStructName, recurseLevel+1)
					}
658
					if err != nil {
659 660
						errcount++
						val = fmt.Sprintf("<unreadable: %s>", err.Error())
661 662 663
					}

					fields = append(fields, fmt.Sprintf("%s: %s", field.Name, val))
664 665 666 667

					if errcount > maxErrCount {
						fields = append(fields, fmt.Sprintf("...+%d more", len(t.Field)-i))
					}
668
				}
669 670 671 672
				if printStructName {
					return fmt.Sprintf("%s {%s}", t.StructName, strings.Join(fields, ", ")), nil
				}
				return fmt.Sprintf("{%s}", strings.Join(fields, ", ")), nil
673
			}
674
			// no fields
E
epipho 已提交
675
			if printStructName {
676
				return fmt.Sprintf("%s {...}", t.StructName), nil
E
epipho 已提交
677
			}
678
			return "{...}", nil
679 680
		}
	case *dwarf.ArrayType:
681
		return v.loadArrayValues(recurseLevel)
682
	case *dwarf.ComplexType:
683
		return v.readComplex(t.ByteSize)
684
	case *dwarf.IntType:
685
		return v.readInt(t.ByteSize)
E
epipho 已提交
686
	case *dwarf.UintType:
687
		return v.readUint(t.ByteSize)
688
	case *dwarf.FloatType:
689
		return v.readFloat(t.ByteSize)
E
epipho 已提交
690
	case *dwarf.BoolType:
691
		return v.readBool()
692
	case *dwarf.FuncType:
693
		return v.readFunctionPtr()
694 695 696 697
	case *dwarf.VoidType:
		return "(void)", nil
	case *dwarf.UnspecifiedType:
		return "(unknown)", nil
698 699
	default:
		fmt.Printf("Unknown type: %T\n", t)
700 701
	}

702
	return "", fmt.Errorf("could not find value for type %s", v.dwarfType)
703 704
}

705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725
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 已提交
726
func (thread *Thread) readString(addr uintptr) (string, error) {
727 728 729 730
	// string data structure is always two ptrs in size. Addr, followed by len
	// http://research.swtch.com/godata

	// read len
731
	val, err := thread.readMemory(addr+uintptr(thread.dbp.arch.PtrSize()), thread.dbp.arch.PtrSize())
732
	if err != nil {
733
		return "", fmt.Errorf("could not read string len %s", err)
734
	}
735
	strlen := int(binary.LittleEndian.Uint64(val))
736 737 738 739 740 741 742 743
	if strlen < 0 {
		return "", fmt.Errorf("invalid length: %d", strlen)
	}

	count := strlen
	if count > maxArrayValues {
		count = maxArrayValues
	}
744 745

	// read addr
746
	val, err = thread.readMemory(addr, thread.dbp.arch.PtrSize())
747
	if err != nil {
748
		return "", fmt.Errorf("could not read string pointer %s", err)
749 750
	}
	addr = uintptr(binary.LittleEndian.Uint64(val))
D
Derek Parker 已提交
751 752 753
	if addr == 0 {
		return "", nil
	}
D
Derek Parker 已提交
754

755
	val, err = thread.readMemory(addr, count)
756
	if err != nil {
757
		return "", fmt.Errorf("could not read string at %#v due to %s", addr, err)
758 759
	}

760 761 762 763 764 765 766
	retstr := *(*string)(unsafe.Pointer(&val))

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

	return retstr, nil
767 768
}

769 770
func (v *Variable) loadSliceInfo(t *dwarf.StructType) error {
	var err error
E
epipho 已提交
771 772 773
	for _, f := range t.Field {
		switch f.Name {
		case "array":
774 775 776 777 778 779 780 781 782 783
			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 已提交
784 785
			}
		case "len":
786 787 788
			lstrAddr, err := v.toField(f)
			if err == nil {
				err = lstrAddr.loadValue(true)
E
epipho 已提交
789
			}
790 791
			if err == nil {
				v.Len, err = strconv.ParseInt(lstrAddr.Value, 10, 64)
E
epipho 已提交
792 793
			}
		case "cap":
794 795 796
			cstrAddr, err := v.toField(f)
			if err == nil {
				err = cstrAddr.loadValue(true)
E
epipho 已提交
797
			}
798 799
			if err == nil {
				v.Cap, err = strconv.ParseInt(cstrAddr.Value, 10, 64)
E
epipho 已提交
800 801 802 803
			}
		}
	}

804
	if err != nil {
805
		return nil
806 807
	}

808 809 810
	v.stride = v.fieldType.Size()
	if _, ok := v.fieldType.(*dwarf.PtrType); ok {
		v.stride = int64(v.thread.dbp.arch.PtrSize())
811
	}
812 813

	return nil
814 815
}

816
func (v *Variable) loadArrayValues(recurseLevel int) (string, error) {
E
epipho 已提交
817
	vals := make([]string, 0)
818
	errcount := 0
819

820
	for i := int64(0); i < v.Len; i++ {
821 822
		// Cap number of elements
		if i >= maxArrayValues {
823
			vals = append(vals, fmt.Sprintf("...+%d more", v.Len-maxArrayValues))
824 825 826
			break
		}

827 828 829 830 831
		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 已提交
832
		if err != nil {
833 834
			errcount++
			val = fmt.Sprintf("<unreadable: %s>", err.Error())
E
epipho 已提交
835
		}
836

E
epipho 已提交
837
		vals = append(vals, val)
838
		if errcount > maxErrCount {
839
			vals = append(vals, fmt.Sprintf("...+%d more", v.Len-i))
840 841
			break
		}
842
	}
843 844 845 846 847 848

	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
	}
849 850
}

851
func (v *Variable) readComplex(size int64) (string, error) {
852 853 854 855 856 857 858 859 860
	var fs int64
	switch size {
	case 8:
		fs = 4
	case 16:
		fs = 8
	default:
		return "", fmt.Errorf("invalid size (%d) for complex type", size)
	}
861
	r, err := v.readFloat(fs)
862 863 864
	if err != nil {
		return "", err
	}
865 866 867
	imagvar := *v
	imagvar.Addr += uintptr(fs)
	i, err := imagvar.readFloat(fs)
868 869 870
	if err != nil {
		return "", err
	}
871
	return fmt.Sprintf("(%s + %si)", r, i), nil
872 873
}

874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 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
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))
}

949 950
func (v *Variable) readInt(size int64) (string, error) {
	n, err := v.thread.readIntRaw(v.Addr, size)
D
Derek Parker 已提交
951 952 953 954 955 956
	if err != nil {
		return "", err
	}
	return strconv.FormatInt(n, 10), nil
}

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

960
	val, err := thread.readMemory(addr, int(size))
961
	if err != nil {
D
Derek Parker 已提交
962
		return 0, err
963 964
	}

965 966
	switch size {
	case 1:
E
epipho 已提交
967
		n = int64(val[0])
968
	case 2:
E
epipho 已提交
969
		n = int64(binary.LittleEndian.Uint16(val))
970
	case 4:
E
epipho 已提交
971
		n = int64(binary.LittleEndian.Uint32(val))
972
	case 8:
E
epipho 已提交
973
		n = int64(binary.LittleEndian.Uint64(val))
974
	}
975

D
Derek Parker 已提交
976
	return n, nil
E
epipho 已提交
977 978
}

979 980
func (v *Variable) readUint(size int64) (string, error) {
	n, err := v.thread.readUintRaw(v.Addr, size)
D
Derek Parker 已提交
981 982 983 984 985 986
	if err != nil {
		return "", err
	}
	return strconv.FormatUint(n, 10), nil
}

987
func (v *Variable) writeUint(signed bool, value string, size int64) error {
988 989 990 991
	var (
		n   uint64
		err error
	)
992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019
	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 已提交
1020
func (thread *Thread) readUintRaw(addr uintptr, size int64) (uint64, error) {
E
epipho 已提交
1021 1022
	var n uint64

1023
	val, err := thread.readMemory(addr, int(size))
E
epipho 已提交
1024
	if err != nil {
D
Derek Parker 已提交
1025
		return 0, err
E
epipho 已提交
1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038
	}

	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 已提交
1039
	return n, nil
1040 1041
}

1042 1043
func (v *Variable) readFloat(size int64) (string, error) {
	val, err := v.thread.readMemory(v.Addr, int(size))
1044 1045 1046 1047 1048
	if err != nil {
		return "", err
	}
	buf := bytes.NewBuffer(val)

D
Derek Parker 已提交
1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059
	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 已提交
1060
	return "", fmt.Errorf("could not read float")
1061 1062
}

1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086
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
}

1087 1088
func (v *Variable) readBool() (string, error) {
	val, err := v.thread.readMemory(v.Addr, 1)
E
epipho 已提交
1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099
	if err != nil {
		return "", err
	}

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

	return "true", nil
}

1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112
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
}

1113 1114
func (v *Variable) readFunctionPtr() (string, error) {
	val, err := v.thread.readMemory(v.Addr, v.thread.dbp.arch.PtrSize())
1115 1116 1117 1118 1119
	if err != nil {
		return "", err
	}

	// dereference pointer to find function pc
1120 1121
	fnaddr := uintptr(binary.LittleEndian.Uint64(val))
	if fnaddr == 0 {
1122 1123
		return "nil", nil
	}
1124

1125
	val, err = v.thread.readMemory(fnaddr, v.thread.dbp.arch.PtrSize())
1126 1127 1128 1129 1130
	if err != nil {
		return "", err
	}

	funcAddr := binary.LittleEndian.Uint64(val)
1131
	fn := v.thread.dbp.goSymTable.PCToFunc(uint64(funcAddr))
1132 1133
	if fn == nil {
		return "", fmt.Errorf("could not find function for %#v", funcAddr)
1134 1135
	}

1136
	return fn.Name, nil
1137 1138
}

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

1143
	_, err := reader.SeekToFunction(scope.PC)
1144
	if err != nil {
E
epipho 已提交
1145 1146 1147 1148 1149
		return nil, err
	}

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

1150
	for entry, err := reader.NextScopeVariable(); entry != nil; entry, err = reader.NextScopeVariable() {
E
epipho 已提交
1151 1152 1153 1154 1155
		if err != nil {
			return nil, err
		}

		if entry.Tag == tag {
1156
			val, err := scope.extractVariableFromEntry(entry)
E
epipho 已提交
1157
			if err != nil {
E
epipho 已提交
1158 1159
				// skip variables that we can't parse yet
				continue
E
epipho 已提交
1160 1161 1162 1163 1164 1165 1166 1167
			}

			vars = append(vars, val)
		}
	}

	return vars, nil
}