github.com/undoio/delve@v1.9.0/pkg/proc/breakpoints.go (about)

     1  package proc
     2  
     3  import (
     4  	"debug/dwarf"
     5  	"errors"
     6  	"fmt"
     7  	"go/ast"
     8  	"go/constant"
     9  	"go/parser"
    10  	"go/token"
    11  	"reflect"
    12  
    13  	"github.com/undoio/delve/pkg/dwarf/godwarf"
    14  	"github.com/undoio/delve/pkg/dwarf/op"
    15  	"github.com/undoio/delve/pkg/dwarf/reader"
    16  	"github.com/undoio/delve/pkg/goversion"
    17  	"github.com/undoio/delve/pkg/proc/internal/ebpf"
    18  )
    19  
    20  const (
    21  	// UnrecoveredPanic is the name given to the unrecovered panic breakpoint.
    22  	UnrecoveredPanic = "unrecovered-panic"
    23  
    24  	// FatalThrow is the name given to the breakpoint triggered when the target
    25  	// process dies because of a fatal runtime error.
    26  	FatalThrow = "runtime-fatal-throw"
    27  
    28  	// HardcodedBreakpoint is the name given to hardcoded breakpoints (for
    29  	// example: calls to runtime.Breakpoint)
    30  	HardcodedBreakpoint = "hardcoded-breakpoint"
    31  
    32  	unrecoveredPanicID    = -1
    33  	fatalThrowID          = -2
    34  	hardcodedBreakpointID = -3
    35  
    36  	NoLogicalID = -1000 // Logical breakpoint ID for breakpoints internal breakpoints.
    37  )
    38  
    39  // Breakpoint represents a physical breakpoint. Stores information on the break
    40  // point including the byte of data that originally was stored at that
    41  // address.
    42  type Breakpoint struct {
    43  	// File & line information for printing.
    44  	FunctionName string
    45  	File         string
    46  	Line         int
    47  
    48  	Addr         uint64 // Address breakpoint is set for.
    49  	OriginalData []byte // If software breakpoint, the data we replace with breakpoint instruction.
    50  
    51  	WatchExpr     string
    52  	WatchType     WatchType
    53  	HWBreakIndex  uint8 // hardware breakpoint index
    54  	watchStackOff int64 // for watchpoints of stack variables, offset of the address from top of the stack
    55  
    56  	// Breaklets is the list of overlapping breakpoints on this physical breakpoint.
    57  	// There can be at most one UserBreakpoint in this list but multiple internal breakpoints are allowed.
    58  	Breaklets []*Breaklet
    59  
    60  	// Breakpoint information
    61  	Logical *LogicalBreakpoint
    62  
    63  	// ReturnInfo describes how to collect return variables when this
    64  	// breakpoint is hit as a return breakpoint.
    65  	returnInfo *returnBreakpointInfo
    66  }
    67  
    68  // Breaklet represents one of multiple breakpoints that can overlap on a
    69  // single physical breakpoint.
    70  type Breaklet struct {
    71  	// Kind describes whether this is a stepping breakpoint (for next'ing or
    72  	// stepping).
    73  	Kind BreakpointKind
    74  
    75  	LogicalID int // ID of the logical breakpoint that owns this physical breakpoint
    76  
    77  	// Cond: if not nil the breakpoint will be triggered only if evaluating Cond returns true
    78  	Cond ast.Expr
    79  
    80  	// DeferReturns: when kind == NextDeferBreakpoint this breakpoint
    81  	// will also check if the caller is runtime.gopanic or if the return
    82  	// address is in the DeferReturns array.
    83  	// Next uses NextDeferBreakpoints for the breakpoint it sets on the
    84  	// deferred function, DeferReturns is populated with the
    85  	// addresses of calls to runtime.deferreturn in the current
    86  	// function. This ensures that the breakpoint on the deferred
    87  	// function only triggers on panic or on the defer call to
    88  	// the function, not when the function is called directly
    89  	DeferReturns []uint64
    90  
    91  	// checkPanicCall checks that the breakpoint happened while the function was
    92  	// called by a panic. It is only checked for WatchOutOfScopeBreakpoint Kind.
    93  	checkPanicCall bool
    94  
    95  	// callback is called if every other condition for this breaklet is met,
    96  	// the return value will determine if the breaklet should be considered
    97  	// active.
    98  	// The callback can have side-effects.
    99  	callback func(th Thread) bool
   100  
   101  	// For WatchOutOfScopeBreakpoints and StackResizeBreakpoints the watchpoint
   102  	// field contains the watchpoint related to this out of scope sentinel.
   103  	watchpoint *Breakpoint
   104  }
   105  
   106  // BreakpointKind determines the behavior of delve when the
   107  // breakpoint is reached.
   108  type BreakpointKind uint16
   109  
   110  const (
   111  	// UserBreakpoint is a user set breakpoint
   112  	UserBreakpoint BreakpointKind = (1 << iota)
   113  	// NextBreakpoint is a breakpoint set by Next, Continue
   114  	// will stop on it and delete it
   115  	NextBreakpoint
   116  	// NextDeferBreakpoint is a breakpoint set by Next on the
   117  	// first deferred function. In addition to checking their condition
   118  	// breakpoints of this kind will also check that the function has been
   119  	// called by runtime.gopanic or through runtime.deferreturn.
   120  	NextDeferBreakpoint
   121  	// StepBreakpoint is a breakpoint set by Step on a CALL instruction,
   122  	// Continue will set a new breakpoint (of NextBreakpoint kind) on the
   123  	// destination of CALL, delete this breakpoint and then continue again
   124  	StepBreakpoint
   125  
   126  	// WatchOutOfScopeBreakpoint is a breakpoint used to detect when a watched
   127  	// stack variable goes out of scope.
   128  	WatchOutOfScopeBreakpoint
   129  
   130  	// StackResizeBreakpoint is a breakpoint used to detect stack resizes to
   131  	// adjust the watchpoint of stack variables.
   132  	StackResizeBreakpoint
   133  
   134  	steppingMask = NextBreakpoint | NextDeferBreakpoint | StepBreakpoint
   135  )
   136  
   137  // WatchType is the watchpoint type
   138  type WatchType uint8
   139  
   140  const (
   141  	WatchRead WatchType = 1 << iota
   142  	WatchWrite
   143  )
   144  
   145  // Read returns true if the hardware breakpoint should trigger on memory reads.
   146  func (wtype WatchType) Read() bool {
   147  	return wtype&WatchRead != 0
   148  }
   149  
   150  // Write returns true if the hardware breakpoint should trigger on memory writes.
   151  func (wtype WatchType) Write() bool {
   152  	return wtype&WatchWrite != 0
   153  }
   154  
   155  // Size returns the size in bytes of the hardware breakpoint.
   156  func (wtype WatchType) Size() int {
   157  	return int(wtype >> 4)
   158  }
   159  
   160  // withSize returns a new HWBreakType with the size set to the specified value
   161  func (wtype WatchType) withSize(sz uint8) WatchType {
   162  	return WatchType((sz << 4) | uint8(wtype&0xf))
   163  }
   164  
   165  var ErrHWBreakUnsupported = errors.New("hardware breakpoints not implemented")
   166  
   167  func (bp *Breakpoint) String() string {
   168  	return fmt.Sprintf("Breakpoint %d at %#v %s:%d", bp.LogicalID(), bp.Addr, bp.File, bp.Line)
   169  }
   170  
   171  func (bp *Breakpoint) LogicalID() int {
   172  	for _, breaklet := range bp.Breaklets {
   173  		if breaklet.Kind == UserBreakpoint {
   174  			return breaklet.LogicalID
   175  		}
   176  	}
   177  	return NoLogicalID
   178  }
   179  
   180  // VerboseDescr returns a string describing parts of the breakpoint struct
   181  // that aren't otherwise user visible, for debugging purposes.
   182  func (bp *Breakpoint) VerboseDescr() []string {
   183  	r := []string{}
   184  
   185  	r = append(r, fmt.Sprintf("OriginalData=%#x", bp.OriginalData))
   186  
   187  	if bp.WatchType != 0 {
   188  		r = append(r, fmt.Sprintf("HWBreakIndex=%#x watchStackOff=%#x", bp.HWBreakIndex, bp.watchStackOff))
   189  	}
   190  
   191  	lbp := bp.Logical
   192  
   193  	for _, breaklet := range bp.Breaklets {
   194  		switch breaklet.Kind {
   195  		case UserBreakpoint:
   196  			r = append(r, fmt.Sprintf("User Cond=%q HitCond=%v", exprToString(breaklet.Cond), lbp.HitCond))
   197  		case NextBreakpoint:
   198  			r = append(r, fmt.Sprintf("Next Cond=%q", exprToString(breaklet.Cond)))
   199  		case NextDeferBreakpoint:
   200  			r = append(r, fmt.Sprintf("NextDefer Cond=%q DeferReturns=%#x", exprToString(breaklet.Cond), breaklet.DeferReturns))
   201  		case StepBreakpoint:
   202  			r = append(r, fmt.Sprintf("Step Cond=%q", exprToString(breaklet.Cond)))
   203  		case WatchOutOfScopeBreakpoint:
   204  			r = append(r, fmt.Sprintf("WatchOutOfScope Cond=%q checkPanicCall=%v", exprToString(breaklet.Cond), breaklet.checkPanicCall))
   205  		case StackResizeBreakpoint:
   206  			r = append(r, fmt.Sprintf("StackResizeBreakpoint Cond=%q", exprToString(breaklet.Cond)))
   207  		default:
   208  			r = append(r, fmt.Sprintf("Unknown %d", breaklet.Kind))
   209  		}
   210  	}
   211  	return r
   212  }
   213  
   214  // BreakpointExistsError is returned when trying to set a breakpoint at
   215  // an address that already has a breakpoint set for it.
   216  type BreakpointExistsError struct {
   217  	File string
   218  	Line int
   219  	Addr uint64
   220  }
   221  
   222  func (bpe BreakpointExistsError) Error() string {
   223  	return fmt.Sprintf("Breakpoint exists at %s:%d at %x", bpe.File, bpe.Line, bpe.Addr)
   224  }
   225  
   226  // InvalidAddressError represents the result of
   227  // attempting to set a breakpoint at an invalid address.
   228  type InvalidAddressError struct {
   229  	Address uint64
   230  }
   231  
   232  func (iae InvalidAddressError) Error() string {
   233  	return fmt.Sprintf("Invalid address %#v\n", iae.Address)
   234  }
   235  
   236  type returnBreakpointInfo struct {
   237  	retFrameCond ast.Expr
   238  	fn           *Function
   239  	frameOffset  int64
   240  	spOffset     int64
   241  }
   242  
   243  // CheckCondition evaluates bp's condition on thread.
   244  func (bp *Breakpoint) checkCondition(tgt *Target, thread Thread, bpstate *BreakpointState) {
   245  	*bpstate = BreakpointState{Breakpoint: bp, Active: false, Stepping: false, SteppingInto: false, CondError: nil}
   246  	for _, breaklet := range bp.Breaklets {
   247  		bpstate.checkCond(tgt, breaklet, thread)
   248  	}
   249  }
   250  
   251  func (bpstate *BreakpointState) checkCond(tgt *Target, breaklet *Breaklet, thread Thread) {
   252  	var condErr error
   253  	active := true
   254  	if breaklet.Cond != nil {
   255  		active, condErr = evalBreakpointCondition(tgt, thread, breaklet.Cond)
   256  	}
   257  
   258  	if condErr != nil && bpstate.CondError == nil {
   259  		bpstate.CondError = condErr
   260  	}
   261  	if !active {
   262  		return
   263  	}
   264  
   265  	switch breaklet.Kind {
   266  	case UserBreakpoint:
   267  		lbp := bpstate.Breakpoint.Logical
   268  		if lbp != nil {
   269  			if g, err := GetG(thread); err == nil {
   270  				lbp.HitCount[g.ID]++
   271  			}
   272  			lbp.TotalHitCount++
   273  		}
   274  		active = checkHitCond(lbp)
   275  
   276  	case StepBreakpoint, NextBreakpoint, NextDeferBreakpoint:
   277  		nextDeferOk := true
   278  		if breaklet.Kind&NextDeferBreakpoint != 0 {
   279  			var err error
   280  			frames, err := ThreadStacktrace(thread, 2)
   281  			if err == nil {
   282  				nextDeferOk, _ = isPanicCall(frames)
   283  				if !nextDeferOk {
   284  					nextDeferOk, _ = isDeferReturnCall(frames, breaklet.DeferReturns)
   285  				}
   286  			}
   287  		}
   288  		active = active && nextDeferOk
   289  		if active {
   290  			bpstate.Stepping = true
   291  			if breaklet.Kind == StepBreakpoint {
   292  				bpstate.SteppingInto = true
   293  			}
   294  		}
   295  
   296  	case WatchOutOfScopeBreakpoint:
   297  		if breaklet.checkPanicCall {
   298  			frames, err := ThreadStacktrace(thread, 2)
   299  			if err == nil {
   300  				ipc, _ := isPanicCall(frames)
   301  				active = active && ipc
   302  			}
   303  		}
   304  
   305  	case StackResizeBreakpoint:
   306  		// no further checks
   307  
   308  	default:
   309  		bpstate.CondError = fmt.Errorf("internal error unknown breakpoint kind %v", breaklet.Kind)
   310  	}
   311  
   312  	if active {
   313  		if breaklet.callback != nil {
   314  			active = breaklet.callback(thread)
   315  		}
   316  		bpstate.Active = active
   317  	}
   318  }
   319  
   320  // checkHitCond evaluates bp's hit condition on thread.
   321  func checkHitCond(lbp *LogicalBreakpoint) bool {
   322  	if lbp == nil || lbp.HitCond == nil {
   323  		return true
   324  	}
   325  	// Evaluate the breakpoint condition.
   326  	switch lbp.HitCond.Op {
   327  	case token.EQL:
   328  		return int(lbp.TotalHitCount) == lbp.HitCond.Val
   329  	case token.NEQ:
   330  		return int(lbp.TotalHitCount) != lbp.HitCond.Val
   331  	case token.GTR:
   332  		return int(lbp.TotalHitCount) > lbp.HitCond.Val
   333  	case token.LSS:
   334  		return int(lbp.TotalHitCount) < lbp.HitCond.Val
   335  	case token.GEQ:
   336  		return int(lbp.TotalHitCount) >= lbp.HitCond.Val
   337  	case token.LEQ:
   338  		return int(lbp.TotalHitCount) <= lbp.HitCond.Val
   339  	case token.REM:
   340  		return int(lbp.TotalHitCount)%lbp.HitCond.Val == 0
   341  	}
   342  	return false
   343  }
   344  
   345  func isPanicCall(frames []Stackframe) (bool, int) {
   346  	// In Go prior to 1.17 the call stack for a panic is:
   347  	//  0. deferred function call
   348  	//  1. runtime.callN
   349  	//  2. runtime.gopanic
   350  	// in Go after 1.17 it is either:
   351  	//  0. deferred function call
   352  	//  1. deferred call wrapper
   353  	//  2. runtime.gopanic
   354  	// or:
   355  	//  0. deferred function call
   356  	//  1. runtime.gopanic
   357  	if len(frames) >= 3 && frames[2].Current.Fn != nil && frames[2].Current.Fn.Name == "runtime.gopanic" {
   358  		return true, 2
   359  	}
   360  	if len(frames) >= 2 && frames[1].Current.Fn != nil && frames[1].Current.Fn.Name == "runtime.gopanic" {
   361  		return true, 1
   362  	}
   363  	return false, 0
   364  }
   365  
   366  func isDeferReturnCall(frames []Stackframe, deferReturns []uint64) (bool, uint64) {
   367  	if len(frames) >= 2 && (len(deferReturns) > 0) {
   368  		// On Go 1.18 and later runtime.deferreturn doesn't use jmpdefer anymore,
   369  		// it's a normal function making normal calls to deferred functions.
   370  		if frames[1].Current.Fn != nil && frames[1].Current.Fn.Name == "runtime.deferreturn" {
   371  			return true, 0
   372  		}
   373  	}
   374  	if len(frames) >= 1 {
   375  		for _, pc := range deferReturns {
   376  			if frames[0].Ret == pc {
   377  				return true, pc
   378  			}
   379  		}
   380  	}
   381  	return false, 0
   382  }
   383  
   384  // IsStepping returns true if bp is an stepping breakpoint.
   385  // User-set breakpoints can overlap with stepping breakpoints, in that case
   386  // both IsUser and IsStepping will be true.
   387  func (bp *Breakpoint) IsStepping() bool {
   388  	for _, breaklet := range bp.Breaklets {
   389  		if breaklet.Kind&steppingMask != 0 {
   390  			return true
   391  		}
   392  	}
   393  	return false
   394  }
   395  
   396  // IsUser returns true if bp is a user-set breakpoint.
   397  // User-set breakpoints can overlap with stepping breakpoints, in that case
   398  // both IsUser and IsStepping will be true.
   399  func (bp *Breakpoint) IsUser() bool {
   400  	for _, breaklet := range bp.Breaklets {
   401  		if breaklet.Kind == UserBreakpoint {
   402  			return true
   403  		}
   404  	}
   405  	return false
   406  }
   407  
   408  // UserBreaklet returns the user breaklet for this breakpoint, or nil if
   409  // none exist.
   410  func (bp *Breakpoint) UserBreaklet() *Breaklet {
   411  	for _, breaklet := range bp.Breaklets {
   412  		if breaklet.Kind == UserBreakpoint {
   413  			return breaklet
   414  		}
   415  	}
   416  	return nil
   417  }
   418  
   419  func evalBreakpointCondition(tgt *Target, thread Thread, cond ast.Expr) (bool, error) {
   420  	if cond == nil {
   421  		return true, nil
   422  	}
   423  	scope, err := GoroutineScope(tgt, thread)
   424  	if err != nil {
   425  		scope, err = ThreadScope(tgt, thread)
   426  		if err != nil {
   427  			return true, err
   428  		}
   429  	}
   430  	v, err := scope.evalAST(cond)
   431  	if err != nil {
   432  		return true, fmt.Errorf("error evaluating expression: %v", err)
   433  	}
   434  	if v.Kind != reflect.Bool {
   435  		return true, errors.New("condition expression not boolean")
   436  	}
   437  	v.loadValue(loadFullValue)
   438  	if v.Unreadable != nil {
   439  		return true, fmt.Errorf("condition expression unreadable: %v", v.Unreadable)
   440  	}
   441  	return constant.BoolVal(v.Value), nil
   442  }
   443  
   444  // NoBreakpointError is returned when trying to
   445  // clear a breakpoint that does not exist.
   446  type NoBreakpointError struct {
   447  	Addr uint64
   448  }
   449  
   450  func (nbp NoBreakpointError) Error() string {
   451  	return fmt.Sprintf("no breakpoint at %#v", nbp.Addr)
   452  }
   453  
   454  // BreakpointMap represents an (address, breakpoint) map.
   455  type BreakpointMap struct {
   456  	M map[uint64]*Breakpoint
   457  
   458  	// Logical is a map of logical breakpoints.
   459  	Logical map[int]*LogicalBreakpoint
   460  
   461  	// WatchOutOfScope is the list of watchpoints that went out of scope during
   462  	// the last resume operation
   463  	WatchOutOfScope []*Breakpoint
   464  }
   465  
   466  // NewBreakpointMap creates a new BreakpointMap.
   467  func NewBreakpointMap() BreakpointMap {
   468  	return BreakpointMap{
   469  		M: make(map[uint64]*Breakpoint),
   470  	}
   471  }
   472  
   473  // SetBreakpoint sets a breakpoint at addr, and stores it in the process wide
   474  // break point table.
   475  func (t *Target) SetBreakpoint(logicalID int, addr uint64, kind BreakpointKind, cond ast.Expr) (*Breakpoint, error) {
   476  	return t.setBreakpointInternal(logicalID, addr, kind, 0, cond)
   477  }
   478  
   479  // SetEBPFTracepoint will attach a uprobe to the function
   480  // specified by 'fnName'.
   481  func (t *Target) SetEBPFTracepoint(fnName string) error {
   482  	// Not every OS/arch that we support has support for eBPF,
   483  	// so check early and return an error if this is called on an
   484  	// unsupported system.
   485  	if !t.proc.SupportsBPF() {
   486  		return errors.New("eBPF is not supported")
   487  	}
   488  	fns, err := t.BinInfo().FindFunction(fnName)
   489  	if err != nil {
   490  		return err
   491  	}
   492  
   493  	// Get information on the Goroutine so we can tell the
   494  	// eBPF program where to find it in order to get the
   495  	// goroutine ID.
   496  	rdr := t.BinInfo().Images[0].DwarfReader()
   497  	rdr.SeekToTypeNamed("runtime.g")
   498  	typ, err := t.BinInfo().findType("runtime.g")
   499  	if err != nil {
   500  		return errors.New("could not find type for runtime.g")
   501  	}
   502  	var goidOffset int64
   503  	switch t := typ.(type) {
   504  	case *godwarf.StructType:
   505  		for _, field := range t.Field {
   506  			if field.Name == "goid" {
   507  				goidOffset = field.ByteOffset
   508  				break
   509  			}
   510  		}
   511  	}
   512  
   513  	for _, fn := range fns {
   514  		err := t.setEBPFTracepointOnFunc(fn, goidOffset)
   515  		if err != nil {
   516  			return err
   517  		}
   518  	}
   519  	return nil
   520  }
   521  
   522  func (t *Target) setEBPFTracepointOnFunc(fn *Function, goidOffset int64) error {
   523  	// Start putting together the argument map. This will tell the eBPF program
   524  	// all of the arguments we want to trace and how to find them.
   525  
   526  	// Start looping through each argument / return parameter for the function we
   527  	// are setting the uprobe on. Parse location information so that we can pass it
   528  	// along to the eBPF program.
   529  	dwarfTree, err := fn.cu.image.getDwarfTree(fn.offset)
   530  	if err != nil {
   531  		return err
   532  	}
   533  	variablesFlags := reader.VariablesOnlyVisible
   534  	if t.BinInfo().Producer() != "" && goversion.ProducerAfterOrEqual(t.BinInfo().Producer(), 1, 15) {
   535  		variablesFlags |= reader.VariablesTrustDeclLine
   536  	}
   537  	_, l, _ := t.BinInfo().PCToLine(fn.Entry)
   538  
   539  	var args []ebpf.UProbeArgMap
   540  	varEntries := reader.Variables(dwarfTree, fn.Entry, l, variablesFlags)
   541  	for _, entry := range varEntries {
   542  		_, dt, err := readVarEntry(entry.Tree, fn.cu.image)
   543  		if err != nil {
   544  			return err
   545  		}
   546  
   547  		offset, pieces, _, err := t.BinInfo().Location(entry, dwarf.AttrLocation, fn.Entry, op.DwarfRegisters{}, nil)
   548  		if err != nil {
   549  			return err
   550  		}
   551  		paramPieces := make([]int, 0, len(pieces))
   552  		for _, piece := range pieces {
   553  			if piece.Kind == op.RegPiece {
   554  				paramPieces = append(paramPieces, int(piece.Val))
   555  			}
   556  		}
   557  		isret, _ := entry.Val(dwarf.AttrVarParam).(bool)
   558  		offset += int64(t.BinInfo().Arch.PtrSize())
   559  		args = append(args, ebpf.UProbeArgMap{
   560  			Offset: offset,
   561  			Size:   dt.Size(),
   562  			Kind:   dt.Common().ReflectKind,
   563  			Pieces: paramPieces,
   564  			InReg:  len(pieces) > 0,
   565  			Ret:    isret,
   566  		})
   567  	}
   568  
   569  	//TODO(aarzilli): inlined calls?
   570  
   571  	// Finally, set the uprobe on the function.
   572  	t.proc.SetUProbe(fn.Name, goidOffset, args)
   573  	return nil
   574  }
   575  
   576  // SetWatchpoint sets a data breakpoint at addr and stores it in the
   577  // process wide break point table.
   578  func (t *Target) SetWatchpoint(logicalID int, scope *EvalScope, expr string, wtype WatchType, cond ast.Expr) (*Breakpoint, error) {
   579  	if (wtype&WatchWrite == 0) && (wtype&WatchRead == 0) {
   580  		return nil, errors.New("at least one of read and write must be set for watchpoint")
   581  	}
   582  
   583  	n, err := parser.ParseExpr(expr)
   584  	if err != nil {
   585  		return nil, err
   586  	}
   587  	xv, err := scope.evalAST(n)
   588  	if err != nil {
   589  		return nil, err
   590  	}
   591  	if xv.Addr == 0 || xv.Flags&VariableFakeAddress != 0 || xv.DwarfType == nil {
   592  		return nil, fmt.Errorf("can not watch %q", expr)
   593  	}
   594  	if xv.Unreadable != nil {
   595  		return nil, fmt.Errorf("expression %q is unreadable: %v", expr, xv.Unreadable)
   596  	}
   597  	if xv.Kind == reflect.UnsafePointer || xv.Kind == reflect.Invalid {
   598  		return nil, fmt.Errorf("can not watch variable of type %s", xv.Kind.String())
   599  	}
   600  	sz := xv.DwarfType.Size()
   601  	if sz <= 0 || sz > int64(t.BinInfo().Arch.PtrSize()) {
   602  		//TODO(aarzilli): it is reasonable to expect to be able to watch string
   603  		//and interface variables and we could support it by watching certain
   604  		//member fields here.
   605  		return nil, fmt.Errorf("can not watch variable of type %s", xv.DwarfType.String())
   606  	}
   607  
   608  	stackWatch := scope.g != nil && !scope.g.SystemStack && xv.Addr >= scope.g.stack.lo && xv.Addr < scope.g.stack.hi
   609  
   610  	if stackWatch && wtype&WatchRead != 0 {
   611  		// In theory this would work except for the fact that the runtime will
   612  		// read them randomly to resize stacks so it doesn't make sense to do
   613  		// this.
   614  		return nil, errors.New("can not watch stack allocated variable for reads")
   615  	}
   616  
   617  	bp, err := t.setBreakpointInternal(logicalID, xv.Addr, UserBreakpoint, wtype.withSize(uint8(sz)), cond)
   618  	if err != nil {
   619  		return bp, err
   620  	}
   621  	bp.WatchExpr = expr
   622  
   623  	if stackWatch {
   624  		bp.watchStackOff = int64(bp.Addr) - int64(scope.g.stack.hi)
   625  		err := t.setStackWatchBreakpoints(scope, bp)
   626  		if err != nil {
   627  			return bp, err
   628  		}
   629  	}
   630  
   631  	return bp, nil
   632  }
   633  
   634  func (t *Target) setBreakpointInternal(logicalID int, addr uint64, kind BreakpointKind, wtype WatchType, cond ast.Expr) (*Breakpoint, error) {
   635  	if valid, err := t.Valid(); !valid {
   636  		recorded, _ := t.Recorded()
   637  		if !recorded {
   638  			return nil, err
   639  		}
   640  	}
   641  	bpmap := t.Breakpoints()
   642  	newBreaklet := &Breaklet{Kind: kind, Cond: cond}
   643  	if kind == UserBreakpoint {
   644  		newBreaklet.LogicalID = logicalID
   645  	}
   646  
   647  	setLogicalBreakpoint := func(bp *Breakpoint) {
   648  		if kind != UserBreakpoint || bp.Logical != nil {
   649  			return
   650  		}
   651  		if bpmap.Logical == nil {
   652  			bpmap.Logical = make(map[int]*LogicalBreakpoint)
   653  		}
   654  		lbp := bpmap.Logical[logicalID]
   655  		if lbp == nil {
   656  			lbp = &LogicalBreakpoint{LogicalID: logicalID}
   657  			lbp.HitCount = make(map[int]uint64)
   658  			lbp.Enabled = true
   659  			bpmap.Logical[logicalID] = lbp
   660  		}
   661  		bp.Logical = lbp
   662  		breaklet := bp.UserBreaklet()
   663  		if breaklet != nil && breaklet.Cond == nil {
   664  			breaklet.Cond = lbp.Cond
   665  		}
   666  		lbp.File = bp.File
   667  		lbp.Line = bp.Line
   668  		fn := t.BinInfo().PCToFunc(bp.Addr)
   669  		if fn != nil {
   670  			lbp.FunctionName = fn.NameWithoutTypeParams()
   671  		}
   672  	}
   673  
   674  	if bp, ok := bpmap.M[addr]; ok {
   675  		if !bp.canOverlap(kind) {
   676  			return bp, BreakpointExistsError{bp.File, bp.Line, bp.Addr}
   677  		}
   678  		bp.Breaklets = append(bp.Breaklets, newBreaklet)
   679  		setLogicalBreakpoint(bp)
   680  		return bp, nil
   681  	}
   682  
   683  	f, l, fn := t.BinInfo().PCToLine(uint64(addr))
   684  
   685  	fnName := ""
   686  	if fn != nil {
   687  		fnName = fn.Name
   688  	}
   689  
   690  	hwidx := uint8(0)
   691  	if wtype != 0 {
   692  		m := make(map[uint8]bool)
   693  		for _, bp := range bpmap.M {
   694  			if bp.WatchType != 0 {
   695  				m[bp.HWBreakIndex] = true
   696  			}
   697  		}
   698  		for hwidx = 0; true; hwidx++ {
   699  			if !m[hwidx] {
   700  				break
   701  			}
   702  		}
   703  	}
   704  
   705  	newBreakpoint := &Breakpoint{
   706  		FunctionName: fnName,
   707  		WatchType:    wtype,
   708  		HWBreakIndex: hwidx,
   709  		File:         f,
   710  		Line:         l,
   711  		Addr:         addr,
   712  	}
   713  
   714  	err := t.proc.WriteBreakpoint(newBreakpoint)
   715  	if err != nil {
   716  		return nil, err
   717  	}
   718  
   719  	newBreakpoint.Breaklets = append(newBreakpoint.Breaklets, newBreaklet)
   720  	setLogicalBreakpoint(newBreakpoint)
   721  
   722  	bpmap.M[addr] = newBreakpoint
   723  
   724  	return newBreakpoint, nil
   725  }
   726  
   727  // canOverlap returns true if a breakpoint of kind can be overlapped to the
   728  // already existing breaklets in bp.
   729  // At most one user breakpoint can be set but multiple internal breakpoints are allowed.
   730  // All other internal breakpoints are allowed to overlap freely.
   731  func (bp *Breakpoint) canOverlap(kind BreakpointKind) bool {
   732  	if kind == UserBreakpoint {
   733  		return !bp.IsUser()
   734  	}
   735  	return true
   736  }
   737  
   738  // ClearBreakpoint clears the breakpoint at addr.
   739  func (t *Target) ClearBreakpoint(addr uint64) error {
   740  	if valid, err := t.Valid(); !valid {
   741  		recorded, _ := t.Recorded()
   742  		if !recorded {
   743  			return err
   744  		}
   745  	}
   746  	bp, ok := t.Breakpoints().M[addr]
   747  	if !ok {
   748  		return NoBreakpointError{Addr: addr}
   749  	}
   750  
   751  	for i := range bp.Breaklets {
   752  		if bp.Breaklets[i].Kind == UserBreakpoint {
   753  			bp.Breaklets[i] = nil
   754  			if bp.WatchExpr == "" {
   755  				bp.Logical = nil
   756  			}
   757  		}
   758  	}
   759  
   760  	_, err := t.finishClearBreakpoint(bp)
   761  	if err != nil {
   762  		return err
   763  	}
   764  
   765  	if bp.WatchExpr != "" && bp.watchStackOff != 0 {
   766  		// stack watchpoint, must remove all its WatchOutOfScopeBreakpoints/StackResizeBreakpoints
   767  		err := t.clearStackWatchBreakpoints(bp)
   768  		if err != nil {
   769  			return err
   770  		}
   771  	}
   772  
   773  	return nil
   774  }
   775  
   776  // ClearSteppingBreakpoints removes all stepping breakpoints from the map,
   777  // calling clearBreakpoint on each one.
   778  func (t *Target) ClearSteppingBreakpoints() error {
   779  	bpmap := t.Breakpoints()
   780  	threads := t.ThreadList()
   781  	for _, bp := range bpmap.M {
   782  		for i := range bp.Breaklets {
   783  			if bp.Breaklets[i].Kind&steppingMask != 0 {
   784  				bp.Breaklets[i] = nil
   785  			}
   786  		}
   787  		cleared, err := t.finishClearBreakpoint(bp)
   788  		if err != nil {
   789  			return err
   790  		}
   791  		if cleared {
   792  			for _, thread := range threads {
   793  				if thread.Breakpoint().Breakpoint == bp {
   794  					thread.Breakpoint().Clear()
   795  				}
   796  			}
   797  		}
   798  	}
   799  	return nil
   800  }
   801  
   802  // finishClearBreakpoint clears nil breaklets from the breaklet list of bp
   803  // and if it is empty erases the breakpoint.
   804  // Returns true if the breakpoint was deleted
   805  func (t *Target) finishClearBreakpoint(bp *Breakpoint) (bool, error) {
   806  	oldBreaklets := bp.Breaklets
   807  	bp.Breaklets = bp.Breaklets[:0]
   808  	for _, breaklet := range oldBreaklets {
   809  		if breaklet != nil {
   810  			bp.Breaklets = append(bp.Breaklets, breaklet)
   811  		}
   812  	}
   813  	if len(bp.Breaklets) > 0 {
   814  		return false, nil
   815  	}
   816  	if err := t.proc.EraseBreakpoint(bp); err != nil {
   817  		return false, err
   818  	}
   819  
   820  	delete(t.Breakpoints().M, bp.Addr)
   821  	if bp.WatchExpr != "" && bp.Logical != nil {
   822  		delete(t.Breakpoints().Logical, bp.Logical.LogicalID)
   823  	}
   824  	return true, nil
   825  }
   826  
   827  // HasSteppingBreakpoints returns true if bpmap has at least one stepping
   828  // breakpoint set.
   829  func (bpmap *BreakpointMap) HasSteppingBreakpoints() bool {
   830  	for _, bp := range bpmap.M {
   831  		if bp.IsStepping() {
   832  			return true
   833  		}
   834  	}
   835  	return false
   836  }
   837  
   838  // HasHWBreakpoints returns true if there are hardware breakpoints.
   839  func (bpmap *BreakpointMap) HasHWBreakpoints() bool {
   840  	for _, bp := range bpmap.M {
   841  		if bp.WatchType != 0 {
   842  			return true
   843  		}
   844  	}
   845  	return false
   846  }
   847  
   848  // BreakpointState describes the state of a breakpoint in a thread.
   849  type BreakpointState struct {
   850  	*Breakpoint
   851  	// Active is true if the condition of any breaklet is met.
   852  	Active bool
   853  	// Stepping is true if one of the active breaklets is a stepping
   854  	// breakpoint.
   855  	Stepping bool
   856  	// SteppingInto is true if one of the active stepping breaklets has Kind ==
   857  	// StepBreakpoint.
   858  	SteppingInto bool
   859  	// CondError contains any error encountered while evaluating the
   860  	// breakpoint's condition.
   861  	CondError error
   862  }
   863  
   864  // Clear zeros the struct.
   865  func (bpstate *BreakpointState) Clear() {
   866  	bpstate.Breakpoint = nil
   867  	bpstate.Active = false
   868  	bpstate.Stepping = false
   869  	bpstate.SteppingInto = false
   870  	bpstate.CondError = nil
   871  }
   872  
   873  func (bpstate *BreakpointState) String() string {
   874  	s := bpstate.Breakpoint.String()
   875  	if bpstate.Active {
   876  		s += " active"
   877  	}
   878  	if bpstate.Stepping {
   879  		s += " stepping"
   880  	}
   881  	return s
   882  }
   883  
   884  func configureReturnBreakpoint(bi *BinaryInfo, bp *Breakpoint, topframe *Stackframe, retFrameCond ast.Expr) {
   885  	if topframe.Current.Fn == nil {
   886  		return
   887  	}
   888  	bp.returnInfo = &returnBreakpointInfo{
   889  		retFrameCond: retFrameCond,
   890  		fn:           topframe.Current.Fn,
   891  		frameOffset:  topframe.FrameOffset(),
   892  		spOffset:     topframe.FrameOffset() - int64(bi.Arch.PtrSize()), // must be the value that SP had at the entry point of the function
   893  	}
   894  }
   895  
   896  func (rbpi *returnBreakpointInfo) Collect(t *Target, thread Thread) []*Variable {
   897  	if rbpi == nil {
   898  		return nil
   899  	}
   900  
   901  	g, err := GetG(thread)
   902  	if err != nil {
   903  		return returnInfoError("could not get g", err, thread.ProcessMemory())
   904  	}
   905  	scope, err := GoroutineScope(t, thread)
   906  	if err != nil {
   907  		return returnInfoError("could not get scope", err, thread.ProcessMemory())
   908  	}
   909  	v, err := scope.evalAST(rbpi.retFrameCond)
   910  	if err != nil || v.Unreadable != nil || v.Kind != reflect.Bool {
   911  		// This condition was evaluated as part of the breakpoint condition
   912  		// evaluation, if the errors happen they will be reported as part of the
   913  		// condition errors.
   914  		return nil
   915  	}
   916  	if !constant.BoolVal(v.Value) {
   917  		// Breakpoint not hit as a return breakpoint.
   918  		return nil
   919  	}
   920  
   921  	oldFrameOffset := rbpi.frameOffset + int64(g.stack.hi)
   922  	oldSP := uint64(rbpi.spOffset + int64(g.stack.hi))
   923  	err = fakeFunctionEntryScope(scope, rbpi.fn, oldFrameOffset, oldSP)
   924  	if err != nil {
   925  		return returnInfoError("could not read function entry", err, thread.ProcessMemory())
   926  	}
   927  
   928  	vars, err := scope.Locals(0)
   929  	if err != nil {
   930  		return returnInfoError("could not evaluate return variables", err, thread.ProcessMemory())
   931  	}
   932  	vars = filterVariables(vars, func(v *Variable) bool {
   933  		return (v.Flags & VariableReturnArgument) != 0
   934  	})
   935  
   936  	return vars
   937  }
   938  
   939  func returnInfoError(descr string, err error, mem MemoryReadWriter) []*Variable {
   940  	v := newConstant(constant.MakeString(fmt.Sprintf("%s: %v", descr, err.Error())), mem)
   941  	v.Name = "return value read error"
   942  	return []*Variable{v}
   943  }
   944  
   945  // LogicalBreakpoint represents a breakpoint set by a user.
   946  // A logical breakpoint can be associated with zero or many physical
   947  // breakpoints.
   948  // Where a physical breakpoint is associated with a specific instruction
   949  // address a logical breakpoint is associated with a source code location.
   950  // Therefore a logical breakpoint can be associated with zero or many
   951  // physical breakpoints.
   952  // It will have one or more physical breakpoints when source code has been
   953  // inlined (or in the case of type parametric code).
   954  // It will have zero physical breakpoints when it represents a deferred
   955  // breakpoint for code that will be loaded in the future.
   956  type LogicalBreakpoint struct {
   957  	LogicalID    int
   958  	Name         string
   959  	FunctionName string
   960  	File         string
   961  	Line         int
   962  	Enabled      bool
   963  
   964  	Tracepoint  bool // Tracepoint flag
   965  	TraceReturn bool
   966  	Goroutine   bool     // Retrieve goroutine information
   967  	Stacktrace  int      // Number of stack frames to retrieve
   968  	Variables   []string // Variables to evaluate
   969  	LoadArgs    *LoadConfig
   970  	LoadLocals  *LoadConfig
   971  
   972  	HitCount      map[int]uint64 // Number of times a breakpoint has been reached in a certain goroutine
   973  	TotalHitCount uint64         // Number of times a breakpoint has been reached
   974  
   975  	// HitCond: if not nil the breakpoint will be triggered only if the evaluated HitCond returns
   976  	// true with the TotalHitCount.
   977  	HitCond *struct {
   978  		Op  token.Token
   979  		Val int
   980  	}
   981  
   982  	// Cond: if not nil the breakpoint will be triggered only if evaluating Cond returns true
   983  	Cond ast.Expr
   984  
   985  	UserData interface{} // Any additional information about the breakpoint
   986  }