debugger.go 35.0 KB
Newer Older
D
Dan Mace 已提交
1 2 3
package debugger

import (
4
	"debug/dwarf"
5
	"errors"
D
Dan Mace 已提交
6
	"fmt"
7
	"go/parser"
L
Luke Hoban 已提交
8
	"path/filepath"
D
Dan Mace 已提交
9
	"regexp"
L
Luke Hoban 已提交
10 11
	"runtime"
	"strings"
12
	"sync"
13
	"time"
D
Dan Mace 已提交
14

15 16 17 18 19 20 21
	"github.com/go-delve/delve/pkg/goversion"
	"github.com/go-delve/delve/pkg/logflags"
	"github.com/go-delve/delve/pkg/proc"
	"github.com/go-delve/delve/pkg/proc/core"
	"github.com/go-delve/delve/pkg/proc/gdbserial"
	"github.com/go-delve/delve/pkg/proc/native"
	"github.com/go-delve/delve/service/api"
D
Derek Parker 已提交
22
	"github.com/sirupsen/logrus"
D
Dan Mace 已提交
23 24
)

D
Derek Parker 已提交
25 26 27
// Debugger service.
//
// Debugger provides a higher level of
D
Derek Parker 已提交
28
// abstraction over proc.Process.
D
Derek Parker 已提交
29 30 31 32
// It handles converting from internal types to
// the types expected by clients. It also handles
// functionality needed by clients, but not needed in
// lower lever packages such as proc.
D
Dan Mace 已提交
33
type Debugger struct {
D
Derek Parker 已提交
34
	config *Config
35 36
	// arguments to launch a new process.
	processArgs []string
D
Derek Parker 已提交
37
	// TODO(DO NOT MERGE WITHOUT) rename to targetMutex
38
	processMutex sync.Mutex
39
	target       proc.Process
D
Derek Parker 已提交
40
	log          *logrus.Entry
41 42 43

	running      bool
	runningMutex sync.Mutex
D
Dan Mace 已提交
44 45 46 47 48 49 50 51
}

// Config provides the configuration to start a Debugger.
//
// Only one of ProcessArgs or AttachPid should be specified. If ProcessArgs is
// provided, a new process will be launched. Otherwise, the debugger will try
// to attach to an existing process with AttachPid.
type Config struct {
E
Evgeny L 已提交
52 53 54 55
	// WorkingDir is working directory of the new process. This field is used
	// only when launching a new process.
	WorkingDir string

D
Dan Mace 已提交
56 57 58
	// AttachPid is the PID of an existing process to which the debugger should
	// attach.
	AttachPid int
59

60
	// CoreFile specifies the path to the core dump to open.
61
	CoreFile string
62 63
	// Backend specifies the debugger backend.
	Backend string
64 65 66

	// Foreground lets target process access stdin.
	Foreground bool
67 68 69 70

	// DebugInfoDirectories is the list of directories to look for
	// when resolving external debug info files.
	DebugInfoDirectories []string
71 72 73 74 75

	// CheckGoVersion is true if the debugger should check the version of Go
	// used to compile the executable and refuse to work on incompatible
	// versions.
	CheckGoVersion bool
D
Dan Mace 已提交
76 77
}

78 79 80
// New creates a new Debugger. ProcessArgs specify the commandline arguments for the
// new process.
func New(config *Config, processArgs []string) (*Debugger, error) {
81
	logger := logflags.DebuggerLogger()
82
	d := &Debugger{
83 84
		config:      config,
		processArgs: processArgs,
D
Derek Parker 已提交
85
		log:         logger,
D
Dan Mace 已提交
86 87 88
	}

	// Create the process by either attaching or launching.
89 90
	switch {
	case d.config.AttachPid > 0:
D
Derek Parker 已提交
91
		d.log.Infof("attaching to pid %d", d.config.AttachPid)
92
		path := ""
93 94
		if len(d.processArgs) > 0 {
			path = d.processArgs[0]
95 96
		}
		p, err := d.Attach(d.config.AttachPid, path)
D
Dan Mace 已提交
97
		if err != nil {
98
			err = go11DecodeErrorCheck(err)
99
			return nil, attachErrorMessage(d.config.AttachPid, err)
D
Dan Mace 已提交
100
		}
D
Derek Parker 已提交
101
		d.target = p
102 103

	case d.config.CoreFile != "":
104 105 106 107
		var p proc.Process
		var err error
		switch d.config.Backend {
		case "rr":
D
Derek Parker 已提交
108
			d.log.Infof("opening trace %s", d.config.CoreFile)
109
			p, err = gdbserial.Replay(d.config.CoreFile, false, false, d.config.DebugInfoDirectories)
110
		default:
D
Derek Parker 已提交
111
			d.log.Infof("opening core file %s (executable %s)", d.config.CoreFile, d.processArgs[0])
112
			p, err = core.OpenCore(d.config.CoreFile, d.processArgs[0], d.config.DebugInfoDirectories)
113
		}
114
		if err != nil {
115
			err = go11DecodeErrorCheck(err)
116 117 118
			return nil, err
		}
		d.target = p
119 120 121 122
		if err := d.checkGoVersion(); err != nil {
			d.target.Detach(true)
			return nil, err
		}
123 124

	default:
D
Derek Parker 已提交
125
		d.log.Infof("launching process with args: %v", d.processArgs)
126
		p, err := d.Launch(d.processArgs, d.config.WorkingDir)
D
Dan Mace 已提交
127
		if err != nil {
128
			if err != proc.ErrNotExecutable && err != proc.ErrUnsupportedLinuxArch && err != proc.ErrUnsupportedWindowsArch && err != proc.ErrUnsupportedDarwinArch {
129
				err = go11DecodeErrorCheck(err)
130 131 132
				err = fmt.Errorf("could not launch process: %s", err)
			}
			return nil, err
D
Dan Mace 已提交
133
		}
D
Derek Parker 已提交
134
		d.target = p
135 136 137 138
		if err := d.checkGoVersion(); err != nil {
			d.target.Detach(true)
			return nil, err
		}
D
Dan Mace 已提交
139
	}
140
	return d, nil
D
Dan Mace 已提交
141 142
}

143 144 145 146 147 148 149 150 151 152 153 154
// canRestart returns true if the target was started with Launch and can be restarted
func (d *Debugger) canRestart() bool {
	switch {
	case d.config.AttachPid > 0:
		return false
	case d.config.CoreFile != "":
		return false
	default:
		return true
	}
}

155 156 157 158 159 160 161 162 163 164 165
func (d *Debugger) checkGoVersion() error {
	if !d.config.CheckGoVersion {
		return nil
	}
	producer := d.target.BinInfo().Producer()
	if producer == "" {
		return nil
	}
	return goversion.Compatible(producer)
}

166
// Launch will start a process with the given args and working directory.
167
func (d *Debugger) Launch(processArgs []string, wd string) (proc.Process, error) {
168 169
	switch d.config.Backend {
	case "native":
170
		return native.Launch(processArgs, wd, d.config.Foreground, d.config.DebugInfoDirectories)
171
	case "lldb":
172
		return betterGdbserialLaunchError(gdbserial.LLDBLaunch(processArgs, wd, d.config.Foreground, d.config.DebugInfoDirectories))
173
	case "rr":
174
		p, _, err := gdbserial.RecordAndReplay(processArgs, wd, false, d.config.DebugInfoDirectories)
175
		return p, err
176 177
	case "default":
		if runtime.GOOS == "darwin" {
178
			return betterGdbserialLaunchError(gdbserial.LLDBLaunch(processArgs, wd, d.config.Foreground, d.config.DebugInfoDirectories))
179
		}
180
		return native.Launch(processArgs, wd, d.config.Foreground, d.config.DebugInfoDirectories)
181 182 183 184 185 186 187 188 189 190
	default:
		return nil, fmt.Errorf("unknown backend %q", d.config.Backend)
	}
}

// ErrNoAttachPath is the error returned when the client tries to attach to
// a process on macOS using the lldb backend without specifying the path to
// the target's executable.
var ErrNoAttachPath = errors.New("must specify executable path on macOS")

191
// Attach will attach to the process specified by 'pid'.
192
func (d *Debugger) Attach(pid int, path string) (proc.Process, error) {
193 194
	switch d.config.Backend {
	case "native":
195
		return native.Attach(pid, d.config.DebugInfoDirectories)
196
	case "lldb":
197
		return betterGdbserialLaunchError(gdbserial.LLDBAttach(pid, path, d.config.DebugInfoDirectories))
198 199
	case "default":
		if runtime.GOOS == "darwin" {
200
			return betterGdbserialLaunchError(gdbserial.LLDBAttach(pid, path, d.config.DebugInfoDirectories))
201
		}
202
		return native.Attach(pid, d.config.DebugInfoDirectories)
203 204 205 206 207
	default:
		return nil, fmt.Errorf("unknown backend %q", d.config.Backend)
	}
}

208
var errMacOSBackendUnavailable = errors.New("debugserver or lldb-server not found: install XCode's command line tools or lldb-server")
209 210 211 212 213 214 215 216 217

func betterGdbserialLaunchError(p proc.Process, err error) (proc.Process, error) {
	if runtime.GOOS != "darwin" {
		return p, err
	}
	if _, isUnavailable := err.(*gdbserial.ErrBackendUnavailable); !isUnavailable {
		return p, err
	}

218
	return p, errMacOSBackendUnavailable
219 220
}

D
Derek Parker 已提交
221 222
// ProcessPid returns the PID of the process
// the debugger is debugging.
D
Derek Parker 已提交
223
func (d *Debugger) ProcessPid() int {
D
Derek Parker 已提交
224
	return d.target.Pid()
D
Derek Parker 已提交
225 226
}

227 228 229
// LastModified returns the time that the process' executable was last
// modified.
func (d *Debugger) LastModified() time.Time {
230
	return d.target.BinInfo().LastModified()
231 232
}

D
Derek Parker 已提交
233 234
const deferReturn = "runtime.deferreturn"

D
Derek Parker 已提交
235
// FunctionReturnLocations returns all return locations
D
Derek Parker 已提交
236 237
// for the given function, a list of addresses corresponding
// to 'ret' or 'call runtime.deferreturn'.
D
Derek Parker 已提交
238
func (d *Debugger) FunctionReturnLocations(fnName string) ([]uint64, error) {
D
Derek Parker 已提交
239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268
	var (
		p = d.target
		g = p.SelectedGoroutine()
	)

	fn, ok := p.BinInfo().LookupFunc[fnName]
	if !ok {
		return nil, fmt.Errorf("unable to find function %s", fnName)
	}

	var regs proc.Registers
	var mem proc.MemoryReadWriter = p.CurrentThread()
	if g.Thread != nil {
		mem = g.Thread
		regs, _ = g.Thread.Registers(false)
	}
	instructions, err := proc.Disassemble(mem, regs, p.Breakpoints(), p.BinInfo(), fn.Entry, fn.End)
	if err != nil {
		return nil, err
	}

	var addrs []uint64
	for _, instruction := range instructions {
		if instruction.IsRet() {
			addrs = append(addrs, instruction.Loc.PC)
		}
	}
	addrs = append(addrs, proc.FindDeferReturnCalls(instructions)...)

	return addrs, nil
D
Derek Parker 已提交
269 270
}

D
Derek Parker 已提交
271 272 273
// Detach detaches from the target process.
// If `kill` is true we will kill the process after
// detaching.
D
Dan Mace 已提交
274
func (d *Debugger) Detach(kill bool) error {
275 276 277 278 279 280 281
	d.processMutex.Lock()
	defer d.processMutex.Unlock()

	return d.detach(kill)
}

func (d *Debugger) detach(kill bool) error {
A
aarzilli 已提交
282 283
	if d.config.AttachPid == 0 {
		kill = true
284
	}
A
aarzilli 已提交
285
	return d.target.Detach(kill)
D
Dan Mace 已提交
286 287
}

288 289
var ErrCanNotRestart = errors.New("can not restart this target")

D
Derek Parker 已提交
290 291
// Restart will restart the target process, first killing
// and then exec'ing it again.
292 293
// If the target process is a recording it will restart it from the given
// position. If pos starts with 'c' it's a checkpoint ID, otherwise it's an
294
// event number. If resetArgs is true, newArgs will replace the process args.
295
func (d *Debugger) Restart(rerecord bool, pos string, resetArgs bool, newArgs []string) ([]api.DiscardedBreakpoint, error) {
296 297 298
	d.processMutex.Lock()
	defer d.processMutex.Unlock()

299 300
	recorded, _ := d.target.Recorded()
	if recorded && !rerecord {
301 302 303 304
		return nil, d.target.Restart(pos)
	}

	if pos != "" {
305
		return nil, proc.ErrNotRecorded
306 307
	}

308 309 310 311 312
	if !d.canRestart() {
		return nil, ErrCanNotRestart
	}

	if valid, _ := d.target.Valid(); valid && !recorded {
D
Derek Parker 已提交
313
		// Ensure the process is in a PTRACE_STOP.
L
Luke Hoban 已提交
314
		if err := stopProcess(d.ProcessPid()); err != nil {
315
			return nil, err
D
Derek Parker 已提交
316
		}
A
aarzilli 已提交
317 318 319
	}
	if err := d.detach(true); err != nil {
		return nil, err
D
Derek Parker 已提交
320
	}
321 322 323 324
	if resetArgs {
		d.processArgs = append([]string{d.processArgs[0]}, newArgs...)
	}
	p, err := d.Launch(d.processArgs, d.config.WorkingDir)
D
Derek Parker 已提交
325
	if err != nil {
326
		return nil, fmt.Errorf("could not launch process: %s", err)
D
Derek Parker 已提交
327
	}
328
	discarded := []api.DiscardedBreakpoint{}
329
	for _, oldBp := range d.breakpoints() {
330 331 332
		if oldBp.ID < 0 {
			continue
		}
333
		if len(oldBp.File) > 0 {
334
			var err error
335
			oldBp.Addr, err = proc.FindFileLocation(p, oldBp.File, oldBp.Line)
336
			if err != nil {
337
				discarded = append(discarded, api.DiscardedBreakpoint{Breakpoint: oldBp, Reason: err.Error()})
338 339 340
				continue
			}
		}
341
		newBp, err := p.SetBreakpoint(oldBp.Addr, proc.UserBreakpoint, nil)
342
		if err != nil {
343
			return nil, err
344
		}
345
		if err := copyBreakpointInfo(newBp, oldBp); err != nil {
346
			return nil, err
347 348
		}
	}
D
Derek Parker 已提交
349
	d.target = p
A
aarzilli 已提交
350
	return discarded, nil
D
Derek Parker 已提交
351 352
}

D
Derek Parker 已提交
353
// State returns the current state of the debugger.
354 355 356 357 358
func (d *Debugger) State(nowait bool) (*api.DebuggerState, error) {
	if d.isRunning() && nowait {
		return &api.DebuggerState{Running: true}, nil
	}

359 360
	d.processMutex.Lock()
	defer d.processMutex.Unlock()
361
	return d.state(nil)
362 363
}

364
func (d *Debugger) state(retLoadCfg *proc.LoadConfig) (*api.DebuggerState, error) {
365 366
	if _, err := d.target.Valid(); err != nil {
		return nil, err
367 368
	}

369
	var (
370 371
		state     *api.DebuggerState
		goroutine *api.Goroutine
372
	)
373

D
Derek Parker 已提交
374 375
	if d.target.SelectedGoroutine() != nil {
		goroutine = api.ConvertGoroutine(d.target.SelectedGoroutine())
376
	}
D
Dan Mace 已提交
377

378 379
	exited := false
	if _, err := d.target.Valid(); err != nil {
380
		_, exited = err.(*proc.ErrProcessExited)
381 382
	}

383
	state = &api.DebuggerState{
384
		SelectedGoroutine: goroutine,
385
		Exited:            exited,
386
	}
D
Dan Mace 已提交
387

388 389
	for _, thread := range d.target.ThreadList() {
		th := api.ConvertThread(thread)
390 391 392 393 394

		if retLoadCfg != nil {
			th.ReturnValues = convertVars(thread.Common().ReturnValues(*retLoadCfg))
		}

395
		state.Threads = append(state.Threads, th)
396
		if thread.ThreadID() == d.target.CurrentThread().ThreadID() {
397 398 399 400
			state.CurrentThread = th
		}
	}

401
	state.NextInProgress = d.target.Breakpoints().HasInternalBreakpoints()
402

403 404 405 406
	if recorded, _ := d.target.Recorded(); recorded {
		state.When, _ = d.target.When()
	}

407
	return state, nil
D
Dan Mace 已提交
408 409
}

D
Derek Parker 已提交
410
// CreateBreakpoint creates a breakpoint.
D
Derek Parker 已提交
411
func (d *Debugger) CreateBreakpoint(requestedBp *api.Breakpoint) (*api.Breakpoint, error) {
412 413 414
	d.processMutex.Lock()
	defer d.processMutex.Unlock()

415 416 417 418 419
	var (
		createdBp *api.Breakpoint
		addr      uint64
		err       error
	)
420 421 422 423 424

	if requestedBp.Name != "" {
		if err = api.ValidBreakpointName(requestedBp.Name); err != nil {
			return nil, err
		}
425
		if d.findBreakpointByName(requestedBp.Name) != nil {
426 427 428 429
			return nil, errors.New("breakpoint name already exists")
		}
	}

430
	switch {
D
Derek Parker 已提交
431 432
	case requestedBp.TraceReturn:
		addr = requestedBp.Addr
433
	case len(requestedBp.File) > 0:
L
Luke Hoban 已提交
434 435 436 437
		fileName := requestedBp.File
		if runtime.GOOS == "windows" {
			// Accept fileName which is case-insensitive and slash-insensitive match
			fileNameNormalized := strings.ToLower(filepath.ToSlash(fileName))
438
			for _, symFile := range d.target.BinInfo().Sources {
L
Luke Hoban 已提交
439 440 441 442 443 444
				if fileNameNormalized == strings.ToLower(filepath.ToSlash(symFile)) {
					fileName = symFile
					break
				}
			}
		}
445
		addr, err = proc.FindFileLocation(d.target, fileName, requestedBp.Line)
446
	case len(requestedBp.FunctionName) > 0:
447
		addr, err = proc.FindFunctionLocation(d.target, requestedBp.FunctionName, requestedBp.Line)
448
	default:
449 450 451 452 453
		addr = requestedBp.Addr
	}

	if err != nil {
		return nil, err
454
	}
D
Dan Mace 已提交
455

D
Derek Parker 已提交
456
	bp, err := d.target.SetBreakpoint(addr, proc.UserBreakpoint, nil)
457 458 459
	if err != nil {
		return nil, err
	}
460
	if err := copyBreakpointInfo(bp, requestedBp); err != nil {
D
Derek Parker 已提交
461
		if _, err1 := d.target.ClearBreakpoint(bp.Addr); err1 != nil {
462 463 464 465
			err = fmt.Errorf("error while creating breakpoint: %v, additionally the breakpoint could not be properly rolled back: %v", err, err1)
		}
		return nil, err
	}
466
	createdBp = api.ConvertBreakpoint(bp)
D
Derek Parker 已提交
467
	d.log.Infof("created breakpoint: %#v", createdBp)
468
	return createdBp, nil
D
Dan Mace 已提交
469 470
}

471
// AmendBreakpoint will update the breakpoint with the matching ID.
472
func (d *Debugger) AmendBreakpoint(amend *api.Breakpoint) error {
473 474 475
	d.processMutex.Lock()
	defer d.processMutex.Unlock()

476 477 478 479 480 481 482 483 484 485
	original := d.findBreakpoint(amend.ID)
	if original == nil {
		return fmt.Errorf("no breakpoint with ID %d", amend.ID)
	}
	if err := api.ValidBreakpointName(amend.Name); err != nil {
		return err
	}
	return copyBreakpointInfo(original, amend)
}

486 487
// CancelNext will clear internal breakpoints, thus cancelling the 'next',
// 'step' or 'stepout' operation.
488
func (d *Debugger) CancelNext() error {
D
Derek Parker 已提交
489
	return d.target.ClearInternalBreakpoints()
490 491
}

492 493 494
func copyBreakpointInfo(bp *proc.Breakpoint, requested *api.Breakpoint) (err error) {
	bp.Name = requested.Name
	bp.Tracepoint = requested.Tracepoint
D
Derek Parker 已提交
495
	bp.TraceReturn = requested.TraceReturn
496 497 498
	bp.Goroutine = requested.Goroutine
	bp.Stacktrace = requested.Stacktrace
	bp.Variables = requested.Variables
499 500
	bp.LoadArgs = api.LoadConfigToProc(requested.LoadArgs)
	bp.LoadLocals = api.LoadConfigToProc(requested.LoadLocals)
501 502 503 504 505 506 507
	bp.Cond = nil
	if requested.Cond != "" {
		bp.Cond, err = parser.ParseExpr(requested.Cond)
	}
	return err
}

D
Derek Parker 已提交
508
// ClearBreakpoint clears a breakpoint.
D
Derek Parker 已提交
509
func (d *Debugger) ClearBreakpoint(requestedBp *api.Breakpoint) (*api.Breakpoint, error) {
510 511 512
	d.processMutex.Lock()
	defer d.processMutex.Unlock()

D
Derek Parker 已提交
513
	var clearedBp *api.Breakpoint
D
Derek Parker 已提交
514
	bp, err := d.target.ClearBreakpoint(requestedBp.Addr)
515 516 517 518
	if err != nil {
		return nil, fmt.Errorf("Can't clear breakpoint @%x: %s", requestedBp.Addr, err)
	}
	clearedBp = api.ConvertBreakpoint(bp)
D
Derek Parker 已提交
519
	d.log.Infof("cleared breakpoint: %#v", clearedBp)
D
Dan Mace 已提交
520 521 522
	return clearedBp, err
}

D
Derek Parker 已提交
523
// Breakpoints returns the list of current breakpoints.
D
Derek Parker 已提交
524
func (d *Debugger) Breakpoints() []*api.Breakpoint {
525 526 527 528 529 530
	d.processMutex.Lock()
	defer d.processMutex.Unlock()
	return d.breakpoints()
}

func (d *Debugger) breakpoints() []*api.Breakpoint {
D
Derek Parker 已提交
531
	bps := []*api.Breakpoint{}
A
aarzilli 已提交
532
	for _, bp := range d.target.Breakpoints().M {
533 534
		if bp.IsUser() {
			bps = append(bps, api.ConvertBreakpoint(bp))
D
Dan Mace 已提交
535
		}
536
	}
D
Dan Mace 已提交
537 538 539
	return bps
}

D
Derek Parker 已提交
540
// FindBreakpoint returns the breakpoint specified by 'id'.
D
Derek Parker 已提交
541
func (d *Debugger) FindBreakpoint(id int) *api.Breakpoint {
542 543 544
	d.processMutex.Lock()
	defer d.processMutex.Unlock()

545 546 547 548 549 550 551 552
	bp := d.findBreakpoint(id)
	if bp == nil {
		return nil
	}
	return api.ConvertBreakpoint(bp)
}

func (d *Debugger) findBreakpoint(id int) *proc.Breakpoint {
A
aarzilli 已提交
553
	for _, bp := range d.target.Breakpoints().M {
D
Dan Mace 已提交
554 555 556 557 558 559 560
		if bp.ID == id {
			return bp
		}
	}
	return nil
}

561 562
// FindBreakpointByName returns the breakpoint specified by 'name'
func (d *Debugger) FindBreakpointByName(name string) *api.Breakpoint {
563 564 565 566 567 568 569
	d.processMutex.Lock()
	defer d.processMutex.Unlock()
	return d.findBreakpointByName(name)
}

func (d *Debugger) findBreakpointByName(name string) *api.Breakpoint {
	for _, bp := range d.breakpoints() {
570 571 572 573 574 575 576
		if bp.Name == name {
			return bp
		}
	}
	return nil
}

D
Derek Parker 已提交
577
// Threads returns the threads of the target process.
578
func (d *Debugger) Threads() ([]*api.Thread, error) {
579 580 581
	d.processMutex.Lock()
	defer d.processMutex.Unlock()

582 583
	if _, err := d.target.Valid(); err != nil {
		return nil, err
584
	}
585

D
Dan Mace 已提交
586
	threads := []*api.Thread{}
587
	for _, th := range d.target.ThreadList() {
588 589
		threads = append(threads, api.ConvertThread(th))
	}
590
	return threads, nil
D
Dan Mace 已提交
591 592
}

D
Derek Parker 已提交
593
// FindThread returns the thread for the given 'id'.
594
func (d *Debugger) FindThread(id int) (*api.Thread, error) {
595 596 597
	d.processMutex.Lock()
	defer d.processMutex.Unlock()

598 599
	if _, err := d.target.Valid(); err != nil {
		return nil, err
600
	}
601

602 603
	for _, th := range d.target.ThreadList() {
		if th.ThreadID() == id {
604
			return api.ConvertThread(th), nil
D
Dan Mace 已提交
605 606
		}
	}
607
	return nil, nil
D
Dan Mace 已提交
608 609
}

610 611 612 613 614 615 616 617 618 619 620 621
func (d *Debugger) setRunning(running bool) {
	d.runningMutex.Lock()
	d.running = running
	d.runningMutex.Unlock()
}

func (d *Debugger) isRunning() bool {
	d.runningMutex.Lock()
	defer d.runningMutex.Unlock()
	return d.running
}

D
Derek Parker 已提交
622
// Command handles commands which control the debugger lifecycle
D
Dan Mace 已提交
623 624
func (d *Debugger) Command(command *api.DebuggerCommand) (*api.DebuggerState, error) {
	var err error
625 626 627 628

	if command.Name == api.Halt {
		// RequestManualStop does not invoke any ptrace syscalls, so it's safe to
		// access the process directly.
D
Derek Parker 已提交
629
		d.log.Debug("halting")
D
Derek Parker 已提交
630
		err = d.target.RequestManualStop()
631 632
	}

633 634
	withBreakpointInfo := true

635 636 637
	d.processMutex.Lock()
	defer d.processMutex.Unlock()

638 639 640
	d.setRunning(true)
	defer d.setRunning(false)

D
Dan Mace 已提交
641 642
	switch command.Name {
	case api.Continue:
D
Derek Parker 已提交
643
		d.log.Debug("continuing")
644
		err = proc.Continue(d.target)
645 646
	case api.Call:
		d.log.Debugf("function call %s", command.Expr)
647 648 649
		if command.ReturnInfoLoadConfig == nil {
			return nil, errors.New("can not call function with nil ReturnInfoLoadConfig")
		}
650 651 652 653 654 655 656 657
		g := d.target.SelectedGoroutine()
		if command.GoroutineID > 0 {
			g, err = proc.FindGoroutine(d.target, command.GoroutineID)
			if err != nil {
				return nil, err
			}
		}
		err = proc.EvalExpressionWithCalls(d.target, g, command.Expr, *api.LoadConfigToProc(command.ReturnInfoLoadConfig), !command.UnsafeCall)
658
	case api.Rewind:
D
Derek Parker 已提交
659
		d.log.Debug("rewinding")
660 661 662 663 664 665 666
		if err := d.target.Direction(proc.Backward); err != nil {
			return nil, err
		}
		defer func() {
			d.target.Direction(proc.Forward)
		}()
		err = proc.Continue(d.target)
D
Dan Mace 已提交
667
	case api.Next:
D
Derek Parker 已提交
668
		d.log.Debug("nexting")
669
		err = proc.Next(d.target)
D
Dan Mace 已提交
670
	case api.Step:
D
Derek Parker 已提交
671
		d.log.Debug("stepping")
672
		err = proc.Step(d.target)
673
	case api.StepInstruction:
D
Derek Parker 已提交
674
		d.log.Debug("single stepping")
D
Derek Parker 已提交
675
		err = d.target.StepInstruction()
676 677 678 679 680 681 682 683 684
	case api.ReverseStepInstruction:
		d.log.Debug("reverse single stepping")
		if err := d.target.Direction(proc.Backward); err != nil {
			return nil, err
		}
		defer func() {
			d.target.Direction(proc.Forward)
		}()
		err = d.target.StepInstruction()
A
aarzilli 已提交
685
	case api.StepOut:
D
Derek Parker 已提交
686
		d.log.Debug("step out")
687
		err = proc.StepOut(d.target)
D
Dan Mace 已提交
688
	case api.SwitchThread:
D
Derek Parker 已提交
689
		d.log.Debugf("switching to thread %d", command.ThreadID)
D
Derek Parker 已提交
690
		err = d.target.SwitchThread(command.ThreadID)
691
		withBreakpointInfo = false
692
	case api.SwitchGoroutine:
D
Derek Parker 已提交
693
		d.log.Debugf("switching to goroutine %d", command.GoroutineID)
D
Derek Parker 已提交
694
		err = d.target.SwitchGoroutine(command.GoroutineID)
695
		withBreakpointInfo = false
D
Dan Mace 已提交
696
	case api.Halt:
D
Derek Parker 已提交
697
		// RequestManualStop already called
698
		withBreakpointInfo = false
D
Dan Mace 已提交
699
	}
700

D
Dan Mace 已提交
701
	if err != nil {
702
		if exitedErr, exited := err.(proc.ErrProcessExited); command.Name != api.SwitchGoroutine && command.Name != api.SwitchThread && exited {
703 704 705 706 707 708
			state := &api.DebuggerState{}
			state.Exited = true
			state.ExitStatus = exitedErr.Status
			state.Err = errors.New(exitedErr.Error())
			return state, nil
		}
D
Derek Parker 已提交
709
		return nil, err
D
Dan Mace 已提交
710
	}
711
	state, stateErr := d.state(api.LoadConfigToProc(command.ReturnInfoLoadConfig))
712 713 714 715 716 717
	if stateErr != nil {
		return state, stateErr
	}
	if withBreakpointInfo {
		err = d.collectBreakpointInformation(state)
	}
D
Derek Parker 已提交
718 719 720 721 722 723 724 725 726
	for _, th := range state.Threads {
		if th.Breakpoint != nil && th.Breakpoint.TraceReturn {
			for _, v := range th.BreakpointInfo.Arguments {
				if (v.Flags & api.VariableReturnArgument) != 0 {
					th.ReturnValues = append(th.ReturnValues, v)
				}
			}
		}
	}
727
	return state, err
D
Dan Mace 已提交
728 729
}

A
aarzilli 已提交
730
func (d *Debugger) collectBreakpointInformation(state *api.DebuggerState) error {
731
	if state == nil {
A
aarzilli 已提交
732 733 734
		return nil
	}

735
	for i := range state.Threads {
736
		if state.Threads[i].Breakpoint == nil || state.Threads[i].BreakpointInfo != nil {
737 738 739 740 741 742
			continue
		}

		bp := state.Threads[i].Breakpoint
		bpi := &api.BreakpointInfo{}
		state.Threads[i].BreakpointInfo = bpi
A
aarzilli 已提交
743

744
		if bp.Goroutine {
745
			g, err := proc.GetG(d.target.CurrentThread())
746 747 748 749
			if err != nil {
				return err
			}
			bpi.Goroutine = api.ConvertGoroutine(g)
A
aarzilli 已提交
750 751
		}

752
		if bp.Stacktrace > 0 {
753
			rawlocs, err := proc.ThreadStacktrace(d.target.CurrentThread(), bp.Stacktrace)
754 755 756
			if err != nil {
				return err
			}
757
			bpi.Stacktrace, err = d.convertStacktrace(rawlocs, nil)
758 759 760
			if err != nil {
				return err
			}
A
aarzilli 已提交
761
		}
762

763 764 765 766
		thread, found := d.target.FindThread(state.Threads[i].ID)
		if !found {
			return fmt.Errorf("could not find thread %d", state.Threads[i].ID)
		}
767 768 769 770 771 772

		if len(bp.Variables) == 0 && bp.LoadArgs == nil && bp.LoadLocals == nil {
			// don't try to create goroutine scope if there is nothing to load
			continue
		}

773
		s, err := proc.GoroutineScope(thread)
774 775 776
		if err != nil {
			return err
		}
A
aarzilli 已提交
777

778 779 780 781
		if len(bp.Variables) > 0 {
			bpi.Variables = make([]api.Variable, len(bp.Variables))
		}
		for i := range bp.Variables {
782
			v, err := s.EvalVariable(bp.Variables[i], proc.LoadConfig{FollowPointers: true, MaxVariableRecurse: 1, MaxStringLen: 64, MaxArrayValues: 64, MaxStructFields: -1})
783
			if err != nil {
784 785 786
				bpi.Variables[i] = api.Variable{Name: bp.Variables[i], Unreadable: fmt.Sprintf("eval error: %v", err)}
			} else {
				bpi.Variables[i] = *api.ConvertVar(v)
787 788
			}
		}
789 790 791 792 793 794 795 796 797
		if bp.LoadArgs != nil {
			if vars, err := s.FunctionArguments(*api.LoadConfigToProc(bp.LoadArgs)); err == nil {
				bpi.Arguments = convertVars(vars)
			}
		}
		if bp.LoadLocals != nil {
			if locals, err := s.LocalVariables(*api.LoadConfigToProc(bp.LoadLocals)); err == nil {
				bpi.Locals = convertVars(locals)
			}
A
aarzilli 已提交
798
		}
D
Derek Parker 已提交
799
	}
800

A
aarzilli 已提交
801 802 803
	return nil
}

D
Derek Parker 已提交
804
// Sources returns a list of the source files for target binary.
D
Dan Mace 已提交
805
func (d *Debugger) Sources(filter string) ([]string, error) {
806 807 808
	d.processMutex.Lock()
	defer d.processMutex.Unlock()

D
Dan Mace 已提交
809 810 811 812 813 814
	regex, err := regexp.Compile(filter)
	if err != nil {
		return nil, fmt.Errorf("invalid filter argument: %s", err.Error())
	}

	files := []string{}
815
	for _, f := range d.target.BinInfo().Sources {
816 817
		if regex.Match([]byte(f)) {
			files = append(files, f)
D
Dan Mace 已提交
818
		}
819
	}
D
Dan Mace 已提交
820 821 822
	return files, nil
}

D
Derek Parker 已提交
823
// Functions returns a list of functions in the target process.
D
Dan Mace 已提交
824
func (d *Debugger) Functions(filter string) ([]string, error) {
825 826 827
	d.processMutex.Lock()
	defer d.processMutex.Unlock()

828
	return regexFilterFuncs(filter, d.target.BinInfo().Functions)
829 830
}

831
// Types returns all type information in the binary.
A
aarzilli 已提交
832 833 834 835 836 837 838 839 840
func (d *Debugger) Types(filter string) ([]string, error) {
	d.processMutex.Lock()
	defer d.processMutex.Unlock()

	regex, err := regexp.Compile(filter)
	if err != nil {
		return nil, fmt.Errorf("invalid filter argument: %s", err.Error())
	}

841
	types, err := d.target.BinInfo().Types()
A
aarzilli 已提交
842 843 844 845 846 847 848 849 850 851 852 853 854 855
	if err != nil {
		return nil, err
	}

	r := make([]string, 0, len(types))
	for _, typ := range types {
		if regex.Match([]byte(typ)) {
			r = append(r, typ)
		}
	}

	return r, nil
}

856
func regexFilterFuncs(filter string, allFuncs []proc.Function) ([]string, error) {
D
Dan Mace 已提交
857 858 859 860 861 862
	regex, err := regexp.Compile(filter)
	if err != nil {
		return nil, fmt.Errorf("invalid filter argument: %s", err.Error())
	}

	funcs := []string{}
863
	for _, f := range allFuncs {
864
		if regex.Match([]byte(f.Name)) {
865
			funcs = append(funcs, f.Name)
D
Dan Mace 已提交
866
		}
867
	}
D
Dan Mace 已提交
868 869 870
	return funcs, nil
}

D
Derek Parker 已提交
871 872
// PackageVariables returns a list of package variables for the thread,
// optionally regexp filtered using regexp described in 'filter'.
873
func (d *Debugger) PackageVariables(threadID int, filter string, cfg proc.LoadConfig) ([]api.Variable, error) {
874 875 876
	d.processMutex.Lock()
	defer d.processMutex.Unlock()

D
Dan Mace 已提交
877 878 879 880 881 882
	regex, err := regexp.Compile(filter)
	if err != nil {
		return nil, fmt.Errorf("invalid filter argument: %s", err.Error())
	}

	vars := []api.Variable{}
883
	thread, found := d.target.FindThread(threadID)
884 885 886
	if !found {
		return nil, fmt.Errorf("couldn't find thread %d", threadID)
	}
887
	scope, err := proc.ThreadScope(thread)
888 889 890
	if err != nil {
		return nil, err
	}
891
	pv, err := scope.PackageVariables(cfg)
892 893 894 895 896
	if err != nil {
		return nil, err
	}
	for _, v := range pv {
		if regex.Match([]byte(v.Name)) {
897
			vars = append(vars, *api.ConvertVar(v))
D
Dan Mace 已提交
898
		}
899
	}
D
Dan Mace 已提交
900 901 902
	return vars, err
}

D
Derek Parker 已提交
903
// Registers returns string representation of the CPU registers.
A
aarzilli 已提交
904
func (d *Debugger) Registers(threadID int, floatingPoint bool) (api.Registers, error) {
905 906 907
	d.processMutex.Lock()
	defer d.processMutex.Unlock()

908
	thread, found := d.target.FindThread(threadID)
909
	if !found {
A
aarzilli 已提交
910
		return nil, fmt.Errorf("couldn't find thread %d", threadID)
911
	}
A
aarzilli 已提交
912
	regs, err := thread.Registers(floatingPoint)
913
	if err != nil {
A
aarzilli 已提交
914
		return nil, err
915
	}
916
	return api.ConvertRegisters(regs.Slice(floatingPoint)), err
917 918
}

919
func convertVars(pv []*proc.Variable) []api.Variable {
920 921 922
	if pv == nil {
		return nil
	}
923 924
	vars := make([]api.Variable, 0, len(pv))
	for _, v := range pv {
925
		vars = append(vars, *api.ConvertVar(v))
926 927 928 929
	}
	return vars
}

D
Derek Parker 已提交
930
// LocalVariables returns a list of the local variables.
931
func (d *Debugger) LocalVariables(scope api.EvalScope, cfg proc.LoadConfig) ([]api.Variable, error) {
932 933 934
	d.processMutex.Lock()
	defer d.processMutex.Unlock()

935
	s, err := proc.ConvertEvalScope(d.target, scope.GoroutineID, scope.Frame, scope.DeferredCall)
936 937
	if err != nil {
		return nil, err
938
	}
939
	pv, err := s.LocalVariables(cfg)
940 941 942
	if err != nil {
		return nil, err
	}
943
	return convertVars(pv), err
944 945
}

D
Derek Parker 已提交
946
// FunctionArguments returns the arguments to the current function.
947
func (d *Debugger) FunctionArguments(scope api.EvalScope, cfg proc.LoadConfig) ([]api.Variable, error) {
948 949 950
	d.processMutex.Lock()
	defer d.processMutex.Unlock()

951
	s, err := proc.ConvertEvalScope(d.target, scope.GoroutineID, scope.Frame, scope.DeferredCall)
952 953
	if err != nil {
		return nil, err
D
Dan Mace 已提交
954
	}
955
	pv, err := s.FunctionArguments(cfg)
956 957
	if err != nil {
		return nil, err
D
Dan Mace 已提交
958
	}
959
	return convertVars(pv), nil
D
Dan Mace 已提交
960 961
}

D
Derek Parker 已提交
962 963
// EvalVariableInScope will attempt to evaluate the variable represented by 'symbol'
// in the scope provided.
964
func (d *Debugger) EvalVariableInScope(scope api.EvalScope, symbol string, cfg proc.LoadConfig) (*api.Variable, error) {
965 966 967
	d.processMutex.Lock()
	defer d.processMutex.Unlock()

968
	s, err := proc.ConvertEvalScope(d.target, scope.GoroutineID, scope.Frame, scope.DeferredCall)
969 970
	if err != nil {
		return nil, err
971
	}
972
	v, err := s.EvalVariable(symbol, cfg)
973 974
	if err != nil {
		return nil, err
D
Dan Mace 已提交
975
	}
976
	return api.ConvertVar(v), err
D
Dan Mace 已提交
977 978
}

D
Derek Parker 已提交
979 980
// SetVariableInScope will set the value of the variable represented by
// 'symbol' to the value given, in the given scope.
981
func (d *Debugger) SetVariableInScope(scope api.EvalScope, symbol, value string) error {
982 983 984
	d.processMutex.Lock()
	defer d.processMutex.Unlock()

985
	s, err := proc.ConvertEvalScope(d.target, scope.GoroutineID, scope.Frame, scope.DeferredCall)
986 987 988 989 990 991
	if err != nil {
		return err
	}
	return s.SetVariable(symbol, value)
}

D
Derek Parker 已提交
992
// Goroutines will return a list of goroutines in the target process.
993
func (d *Debugger) Goroutines(start, count int) ([]*api.Goroutine, int, error) {
994 995 996
	d.processMutex.Lock()
	defer d.processMutex.Unlock()

997
	goroutines := []*api.Goroutine{}
998
	gs, nextg, err := proc.GoroutinesInfo(d.target, start, count)
999
	if err != nil {
1000
		return nil, 0, err
D
Dan Mace 已提交
1001
	}
1002 1003
	for _, g := range gs {
		goroutines = append(goroutines, api.ConvertGoroutine(g))
D
Dan Mace 已提交
1004
	}
1005
	return goroutines, nextg, err
D
Dan Mace 已提交
1006
}
A
aarzilli 已提交
1007

D
Derek Parker 已提交
1008 1009 1010
// Stacktrace returns a list of Stackframes for the given goroutine. The
// length of the returned list will be min(stack_len, depth).
// If 'full' is true, then local vars, function args, etc will be returned as well.
1011
func (d *Debugger) Stacktrace(goroutineID, depth int, opts api.StacktraceOptions, cfg *proc.LoadConfig) ([]api.Stackframe, error) {
1012 1013 1014
	d.processMutex.Lock()
	defer d.processMutex.Unlock()

1015 1016
	if _, err := d.target.Valid(); err != nil {
		return nil, err
1017 1018
	}

1019
	var rawlocs []proc.Stackframe
A
aarzilli 已提交
1020

1021
	g, err := proc.FindGoroutine(d.target, goroutineID)
A
aarzilli 已提交
1022 1023 1024
	if err != nil {
		return nil, err
	}
A
aarzilli 已提交
1025

A
aarzilli 已提交
1026
	if g == nil {
1027
		rawlocs, err = proc.ThreadStacktrace(d.target.CurrentThread(), depth)
A
aarzilli 已提交
1028
	} else {
1029
		rawlocs, err = g.Stacktrace(depth, proc.StacktraceOptions(opts))
A
aarzilli 已提交
1030 1031 1032
	}
	if err != nil {
		return nil, err
A
aarzilli 已提交
1033 1034
	}

1035
	return d.convertStacktrace(rawlocs, cfg)
A
aarzilli 已提交
1036 1037
}

1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054
// Ancestors returns the stacktraces for the ancestors of a goroutine.
func (d *Debugger) Ancestors(goroutineID, numAncestors, depth int) ([]api.Ancestor, error) {
	d.processMutex.Lock()
	defer d.processMutex.Unlock()

	if _, err := d.target.Valid(); err != nil {
		return nil, err
	}

	g, err := proc.FindGoroutine(d.target, goroutineID)
	if err != nil {
		return nil, err
	}
	if g == nil {
		return nil, errors.New("no selected goroutine")
	}

1055
	ancestors, err := proc.Ancestors(d.target, g, numAncestors)
1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079
	if err != nil {
		return nil, err
	}

	r := make([]api.Ancestor, len(ancestors))
	for i := range ancestors {
		r[i].ID = ancestors[i].ID
		if ancestors[i].Unreadable != nil {
			r[i].Unreadable = ancestors[i].Unreadable.Error()
			continue
		}
		frames, err := ancestors[i].Stack(depth)
		if err != nil {
			r[i].Unreadable = fmt.Sprintf("could not read ancestor stacktrace: %v", err)
			continue
		}
		r[i].Stack, err = d.convertStacktrace(frames, nil)
		if err != nil {
			r[i].Unreadable = fmt.Sprintf("could not read ancestor stacktrace: %v", err)
		}
	}
	return r, nil
}

1080
func (d *Debugger) convertStacktrace(rawlocs []proc.Stackframe, cfg *proc.LoadConfig) ([]api.Stackframe, error) {
1081
	locations := make([]api.Stackframe, 0, len(rawlocs))
A
aarzilli 已提交
1082
	for i := range rawlocs {
1083
		frame := api.Stackframe{
1084 1085 1086 1087
			Location: api.ConvertLocation(rawlocs[i].Call),

			FrameOffset:        rawlocs[i].FrameOffset(),
			FramePointerOffset: rawlocs[i].FramePointerOffset(),
1088 1089

			Defers: d.convertDefers(rawlocs[i].Defers),
1090 1091

			Bottom: rawlocs[i].Bottom,
1092
		}
1093 1094 1095
		if rawlocs[i].Err != nil {
			frame.Err = rawlocs[i].Err.Error()
		}
1096
		if cfg != nil && rawlocs[i].Current.Fn != nil {
1097
			var err error
1098
			scope := proc.FrameToScope(d.target.BinInfo(), d.target.CurrentThread(), nil, rawlocs[i:]...)
1099
			locals, err := scope.LocalVariables(*cfg)
1100 1101 1102
			if err != nil {
				return nil, err
			}
1103
			arguments, err := scope.FunctionArguments(*cfg)
1104 1105 1106
			if err != nil {
				return nil, err
			}
1107 1108 1109

			frame.Locals = convertVars(locals)
			frame.Arguments = convertVars(arguments)
1110 1111
		}
		locations = append(locations, frame)
A
aarzilli 已提交
1112 1113
	}

1114
	return locations, nil
A
aarzilli 已提交
1115
}
1116

1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146
func (d *Debugger) convertDefers(defers []*proc.Defer) []api.Defer {
	r := make([]api.Defer, len(defers))
	for i := range defers {
		ddf, ddl, ddfn := d.target.BinInfo().PCToLine(defers[i].DeferredPC)
		drf, drl, drfn := d.target.BinInfo().PCToLine(defers[i].DeferPC)

		r[i] = api.Defer{
			DeferredLoc: api.ConvertLocation(proc.Location{
				PC:   defers[i].DeferredPC,
				File: ddf,
				Line: ddl,
				Fn:   ddfn,
			}),
			DeferLoc: api.ConvertLocation(proc.Location{
				PC:   defers[i].DeferPC,
				File: drf,
				Line: drl,
				Fn:   drfn,
			}),
			SP: defers[i].SP,
		}

		if defers[i].Unreadable != nil {
			r[i].Unreadable = defers[i].Unreadable.Error()
		}
	}

	return r
}

D
Derek Parker 已提交
1147
// FindLocation will find the location specified by 'locStr'.
1148
func (d *Debugger) FindLocation(scope api.EvalScope, locStr string) ([]api.Location, error) {
1149 1150 1151
	d.processMutex.Lock()
	defer d.processMutex.Unlock()

1152 1153
	if _, err := d.target.Valid(); err != nil {
		return nil, err
1154 1155
	}

1156 1157 1158 1159 1160
	loc, err := parseLocationSpec(locStr)
	if err != nil {
		return nil, err
	}

1161
	s, _ := proc.ConvertEvalScope(d.target, scope.GoroutineID, scope.Frame, scope.DeferredCall)
1162

1163
	locs, err := loc.Find(d, s, locStr)
1164
	for i := range locs {
1165
		file, line, fn := d.target.BinInfo().PCToLine(locs[i].PC)
1166 1167 1168 1169 1170 1171
		locs[i].File = file
		locs[i].Line = line
		locs[i].Function = api.ConvertFunction(fn)
	}
	return locs, err
}
A
aarzilli 已提交
1172

D
Derek Parker 已提交
1173 1174 1175
// Disassemble code between startPC and endPC.
// if endPC == 0 it will find the function containing startPC and disassemble the whole function.
func (d *Debugger) Disassemble(goroutineID int, addr1, addr2 uint64, flavour api.AssemblyFlavour) (api.AsmInstructions, error) {
1176 1177 1178
	d.processMutex.Lock()
	defer d.processMutex.Unlock()

1179 1180
	if _, err := d.target.Valid(); err != nil {
		return nil, err
1181 1182
	}

D
Derek Parker 已提交
1183 1184
	if addr2 == 0 {
		_, _, fn := d.target.BinInfo().PCToLine(addr1)
A
aarzilli 已提交
1185
		if fn == nil {
D
Derek Parker 已提交
1186
			return nil, fmt.Errorf("address %#x does not belong to any function", addr1)
A
aarzilli 已提交
1187
		}
D
Derek Parker 已提交
1188 1189
		addr1 = fn.Entry
		addr2 = fn.End
A
aarzilli 已提交
1190 1191
	}

D
Derek Parker 已提交
1192
	g, err := proc.FindGoroutine(d.target, goroutineID)
1193 1194
	if err != nil {
		return nil, err
A
aarzilli 已提交
1195 1196
	}

1197 1198 1199
	curthread := d.target.CurrentThread()
	if g != nil && g.Thread != nil {
		curthread = g.Thread
D
Derek Parker 已提交
1200
	}
1201 1202 1203
	regs, _ := curthread.Registers(false)

	insts, err := proc.Disassemble(curthread, regs, d.target.Breakpoints(), d.target.BinInfo(), addr1, addr2)
A
aarzilli 已提交
1204 1205 1206 1207 1208 1209
	if err != nil {
		return nil, err
	}
	disass := make(api.AsmInstructions, len(insts))

	for i := range insts {
1210
		disass[i] = api.ConvertAsmInstruction(insts[i], insts[i].Text(proc.AssemblyFlavour(flavour), d.target.BinInfo()))
A
aarzilli 已提交
1211 1212 1213 1214
	}

	return disass, nil
}
1215 1216 1217 1218 1219 1220 1221 1222

// Recorded returns true if the target is a recording.
func (d *Debugger) Recorded() (recorded bool, tracedir string) {
	d.processMutex.Lock()
	defer d.processMutex.Unlock()
	return d.target.Recorded()
}

1223
// Checkpoint will set a checkpoint specified by the locspec.
1224 1225 1226 1227 1228 1229
func (d *Debugger) Checkpoint(where string) (int, error) {
	d.processMutex.Lock()
	defer d.processMutex.Unlock()
	return d.target.Checkpoint(where)
}

1230
// Checkpoints will return a list of checkpoints.
1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244
func (d *Debugger) Checkpoints() ([]api.Checkpoint, error) {
	d.processMutex.Lock()
	defer d.processMutex.Unlock()
	cps, err := d.target.Checkpoints()
	if err != nil {
		return nil, err
	}
	r := make([]api.Checkpoint, len(cps))
	for i := range cps {
		r[i] = api.ConvertCheckpoint(cps[i])
	}
	return r, nil
}

1245
// ClearCheckpoint will clear the checkpoint of the given ID.
1246 1247 1248 1249 1250
func (d *Debugger) ClearCheckpoint(id int) error {
	d.processMutex.Lock()
	defer d.processMutex.Unlock()
	return d.target.ClearCheckpoint(id)
}
1251

1252 1253 1254 1255 1256
// ListDynamicLibraries returns a list of loaded dynamic libraries.
func (d *Debugger) ListDynamicLibraries() []api.Image {
	d.processMutex.Lock()
	defer d.processMutex.Unlock()
	bi := d.target.BinInfo()
1257 1258 1259 1260
	r := make([]api.Image, 0, len(bi.Images)-1)
	// skips the first image because it's the executable file
	for i := range bi.Images[1:] {
		r = append(r, api.ConvertImage(bi.Images[i]))
1261 1262 1263 1264
	}
	return r
}

1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282
func (d *Debugger) GetVersion(out *api.GetVersionOut) error {
	if d.config.CoreFile != "" {
		if d.config.Backend == "rr" {
			out.Backend = "rr"
		} else {
			out.Backend = "core"
		}
	} else {
		if d.config.Backend == "default" {
			if runtime.GOOS == "darwin" {
				out.Backend = "lldb"
			} else {
				out.Backend = "native"
			}
		} else {
			out.Backend = d.config.Backend
		}
	}
1283 1284 1285 1286 1287 1288

	out.TargetGoVersion = d.target.BinInfo().Producer()

	out.MinSupportedVersionOfGo = fmt.Sprintf("%d.%d.0", goversion.MinSupportedVersionOfGoMajor, goversion.MinSupportedVersionOfGoMinor)
	out.MaxSupportedVersionOfGo = fmt.Sprintf("%d.%d.0", goversion.MaxSupportedVersionOfGoMajor, goversion.MaxSupportedVersionOfGoMinor)

1289 1290 1291
	return nil
}

1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303
func go11DecodeErrorCheck(err error) error {
	if _, isdecodeerr := err.(dwarf.DecodeError); !isdecodeerr {
		return err
	}

	gover, ok := goversion.Installed()
	if !ok || !gover.AfterOrEqual(goversion.GoVersion{1, 11, -1, 0, 0, ""}) || goversion.VersionAfterOrEqual(runtime.Version(), 1, 11) {
		return err
	}

	return fmt.Errorf("executables built by Go 1.11 or later need Delve built by Go 1.11 or later")
}