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

     1  package proc
     2  
     3  import (
     4  	"debug/dwarf"
     5  	"errors"
     6  	"fmt"
     7  	"go/constant"
     8  	"reflect"
     9  
    10  	"github.com/undoio/delve/pkg/dwarf/frame"
    11  	"github.com/undoio/delve/pkg/dwarf/op"
    12  	"github.com/undoio/delve/pkg/dwarf/reader"
    13  )
    14  
    15  // This code is partly adapted from runtime.gentraceback in
    16  // $GOROOT/src/runtime/traceback.go
    17  
    18  // Stackframe represents a frame in a system stack.
    19  //
    20  // Each stack frame has two locations Current and Call.
    21  //
    22  // For the topmost stackframe Current and Call are the same location.
    23  //
    24  // For stackframes after the first Current is the location corresponding to
    25  // the return address and Call is the location of the CALL instruction that
    26  // was last executed on the frame. Note however that Call.PC is always equal
    27  // to Current.PC, because finding the correct value for Call.PC would
    28  // require disassembling each function in the stacktrace.
    29  //
    30  // For synthetic stackframes generated for inlined function calls Current.Fn
    31  // is the function containing the inlining and Call.Fn in the inlined
    32  // function.
    33  type Stackframe struct {
    34  	Current, Call Location
    35  
    36  	// Frame registers.
    37  	Regs op.DwarfRegisters
    38  	// High address of the stack.
    39  	stackHi uint64
    40  	// Return address for this stack frame (as read from the stack frame itself).
    41  	Ret uint64
    42  	// Address to the memory location containing the return address
    43  	addrret uint64
    44  	// Err is set if an error occurred during stacktrace
    45  	Err error
    46  	// SystemStack is true if this frame belongs to a system stack.
    47  	SystemStack bool
    48  	// Inlined is true if this frame is actually an inlined call.
    49  	Inlined bool
    50  	// Bottom is true if this is the bottom of the stack
    51  	Bottom bool
    52  
    53  	// lastpc is a memory address guaranteed to belong to the last instruction
    54  	// executed in this stack frame.
    55  	// For the topmost stack frame this will be the same as Current.PC and
    56  	// Call.PC, for other stack frames it will usually be Current.PC-1, but
    57  	// could be different when inlined calls are involved in the stacktrace.
    58  	// Note that this address isn't guaranteed to belong to the start of an
    59  	// instruction and, for this reason, should not be propagated outside of
    60  	// pkg/proc.
    61  	// Use this value to determine active lexical scopes for the stackframe.
    62  	lastpc uint64
    63  
    64  	// TopmostDefer is the defer that would be at the top of the stack when a
    65  	// panic unwind would get to this call frame, in other words it's the first
    66  	// deferred function that will  be called if the runtime unwinds past this
    67  	// call frame.
    68  	TopmostDefer *Defer
    69  
    70  	// Defers is the list of functions deferred by this stack frame (so far).
    71  	Defers []*Defer
    72  }
    73  
    74  // FrameOffset returns the address of the stack frame, absolute for system
    75  // stack frames or as an offset from stackhi for goroutine stacks (a
    76  // negative value).
    77  func (frame *Stackframe) FrameOffset() int64 {
    78  	if frame.SystemStack {
    79  		return frame.Regs.CFA
    80  	}
    81  	return frame.Regs.CFA - int64(frame.stackHi)
    82  }
    83  
    84  // FramePointerOffset returns the value of the frame pointer, absolute for
    85  // system stack frames or as an offset from stackhi for goroutine stacks (a
    86  // negative value).
    87  func (frame *Stackframe) FramePointerOffset() int64 {
    88  	if frame.SystemStack {
    89  		return int64(frame.Regs.BP())
    90  	}
    91  	return int64(frame.Regs.BP()) - int64(frame.stackHi)
    92  }
    93  
    94  // ThreadStacktrace returns the stack trace for thread.
    95  // Note the locations in the array are return addresses not call addresses.
    96  func ThreadStacktrace(thread Thread, depth int) ([]Stackframe, error) {
    97  	g, _ := GetG(thread)
    98  	if g == nil {
    99  		regs, err := thread.Registers()
   100  		if err != nil {
   101  			return nil, err
   102  		}
   103  		so := thread.BinInfo().PCToImage(regs.PC())
   104  		dwarfRegs := *(thread.BinInfo().Arch.RegistersToDwarfRegisters(so.StaticBase, regs))
   105  		dwarfRegs.ChangeFunc = thread.SetReg
   106  		it := newStackIterator(thread.BinInfo(), thread.ProcessMemory(), dwarfRegs, 0, nil, 0)
   107  		return it.stacktrace(depth)
   108  	}
   109  	return g.Stacktrace(depth, 0)
   110  }
   111  
   112  func (g *G) stackIterator(opts StacktraceOptions) (*stackIterator, error) {
   113  	bi := g.variable.bi
   114  	if g.Thread != nil {
   115  		regs, err := g.Thread.Registers()
   116  		if err != nil {
   117  			return nil, err
   118  		}
   119  		so := bi.PCToImage(regs.PC())
   120  		dwarfRegs := *(bi.Arch.RegistersToDwarfRegisters(so.StaticBase, regs))
   121  		dwarfRegs.ChangeFunc = g.Thread.SetReg
   122  		return newStackIterator(
   123  			bi, g.variable.mem,
   124  			dwarfRegs,
   125  			g.stack.hi, g, opts), nil
   126  	}
   127  	so := g.variable.bi.PCToImage(g.PC)
   128  	return newStackIterator(
   129  		bi, g.variable.mem,
   130  		bi.Arch.addrAndStackRegsToDwarfRegisters(so.StaticBase, g.PC, g.SP, g.BP, g.LR),
   131  		g.stack.hi, g, opts), nil
   132  }
   133  
   134  type StacktraceOptions uint16
   135  
   136  const (
   137  	// StacktraceReadDefers requests a stacktrace decorated with deferred calls
   138  	// for each frame.
   139  	StacktraceReadDefers StacktraceOptions = 1 << iota
   140  
   141  	// StacktraceSimple requests a stacktrace where no stack switches will be
   142  	// attempted.
   143  	StacktraceSimple
   144  
   145  	// StacktraceG requests a stacktrace starting with the register
   146  	// values saved in the runtime.g structure.
   147  	StacktraceG
   148  )
   149  
   150  // Stacktrace returns the stack trace for a goroutine.
   151  // Note the locations in the array are return addresses not call addresses.
   152  func (g *G) Stacktrace(depth int, opts StacktraceOptions) ([]Stackframe, error) {
   153  	it, err := g.stackIterator(opts)
   154  	if err != nil {
   155  		return nil, err
   156  	}
   157  	frames, err := it.stacktrace(depth)
   158  	if err != nil {
   159  		return nil, err
   160  	}
   161  	if opts&StacktraceReadDefers != 0 {
   162  		g.readDefers(frames)
   163  	}
   164  	return frames, nil
   165  }
   166  
   167  // NullAddrError is an error for a null address.
   168  type NullAddrError struct{}
   169  
   170  func (n NullAddrError) Error() string {
   171  	return "NULL address"
   172  }
   173  
   174  // stackIterator holds information
   175  // required to iterate and walk the program
   176  // stack.
   177  type stackIterator struct {
   178  	pc    uint64
   179  	top   bool
   180  	atend bool
   181  	frame Stackframe
   182  	bi    *BinaryInfo
   183  	mem   MemoryReadWriter
   184  	err   error
   185  
   186  	stackhi     uint64
   187  	systemstack bool
   188  
   189  	// regs is the register set for the current frame
   190  	regs op.DwarfRegisters
   191  
   192  	g                  *G     // the goroutine being stacktraced, nil if we are stacktracing a goroutine-less thread
   193  	g0_sched_sp        uint64 // value of g0.sched.sp (see comments around its use)
   194  	g0_sched_sp_loaded bool   // g0_sched_sp was loaded from g0
   195  
   196  	opts StacktraceOptions
   197  }
   198  
   199  func newStackIterator(bi *BinaryInfo, mem MemoryReadWriter, regs op.DwarfRegisters, stackhi uint64, g *G, opts StacktraceOptions) *stackIterator {
   200  	systemstack := true
   201  	if g != nil {
   202  		systemstack = g.SystemStack
   203  	}
   204  	return &stackIterator{pc: regs.PC(), regs: regs, top: true, bi: bi, mem: mem, err: nil, atend: false, stackhi: stackhi, systemstack: systemstack, g: g, opts: opts}
   205  }
   206  
   207  // Next points the iterator to the next stack frame.
   208  func (it *stackIterator) Next() bool {
   209  	if it.err != nil || it.atend {
   210  		return false
   211  	}
   212  
   213  	callFrameRegs, ret, retaddr := it.advanceRegs()
   214  	it.frame = it.newStackframe(ret, retaddr)
   215  
   216  	if it.opts&StacktraceSimple == 0 {
   217  		if it.bi.Arch.switchStack(it, &callFrameRegs) {
   218  			return true
   219  		}
   220  	}
   221  
   222  	if it.frame.Ret <= 0 {
   223  		it.atend = true
   224  		return true
   225  	}
   226  
   227  	it.top = false
   228  	it.pc = it.frame.Ret
   229  	it.regs = callFrameRegs
   230  	return true
   231  }
   232  
   233  func (it *stackIterator) switchToGoroutineStack() {
   234  	it.systemstack = false
   235  	it.top = false
   236  	it.pc = it.g.PC
   237  	it.regs.Reg(it.regs.SPRegNum).Uint64Val = it.g.SP
   238  	it.regs.AddReg(it.regs.BPRegNum, op.DwarfRegisterFromUint64(it.g.BP))
   239  	if it.bi.Arch.Name == "arm64" {
   240  		it.regs.Reg(it.regs.LRRegNum).Uint64Val = it.g.LR
   241  	}
   242  }
   243  
   244  // Frame returns the frame the iterator is pointing at.
   245  func (it *stackIterator) Frame() Stackframe {
   246  	it.frame.Bottom = it.atend
   247  	return it.frame
   248  }
   249  
   250  // Err returns the error encountered during stack iteration.
   251  func (it *stackIterator) Err() error {
   252  	return it.err
   253  }
   254  
   255  // frameBase calculates the frame base pseudo-register for DWARF for fn and
   256  // the current frame.
   257  func (it *stackIterator) frameBase(fn *Function) int64 {
   258  	dwarfTree, err := fn.cu.image.getDwarfTree(fn.offset)
   259  	if err != nil {
   260  		return 0
   261  	}
   262  	fb, _, _, _ := it.bi.Location(dwarfTree.Entry, dwarf.AttrFrameBase, it.pc, it.regs, it.mem)
   263  	return fb
   264  }
   265  
   266  func (it *stackIterator) newStackframe(ret, retaddr uint64) Stackframe {
   267  	if retaddr == 0 {
   268  		it.err = NullAddrError{}
   269  		return Stackframe{}
   270  	}
   271  	f, l, fn := it.bi.PCToLine(it.pc)
   272  	if fn == nil {
   273  		f = "?"
   274  		l = -1
   275  	} else {
   276  		it.regs.FrameBase = it.frameBase(fn)
   277  	}
   278  	r := Stackframe{Current: Location{PC: it.pc, File: f, Line: l, Fn: fn}, Regs: it.regs, Ret: ret, addrret: retaddr, stackHi: it.stackhi, SystemStack: it.systemstack, lastpc: it.pc}
   279  	if r.Regs.Reg(it.regs.PCRegNum) == nil {
   280  		r.Regs.AddReg(it.regs.PCRegNum, op.DwarfRegisterFromUint64(it.pc))
   281  	}
   282  	r.Call = r.Current
   283  	if !it.top && r.Current.Fn != nil && it.pc != r.Current.Fn.Entry {
   284  		// if the return address is the entry point of the function that
   285  		// contains it then this is some kind of fake return frame (for example
   286  		// runtime.sigreturn) that didn't actually call the current frame,
   287  		// attempting to get the location of the CALL instruction would just
   288  		// obfuscate what's going on, since there is no CALL instruction.
   289  		switch r.Current.Fn.Name {
   290  		case "runtime.mstart", "runtime.systemstack_switch":
   291  			// these frames are inserted by runtime.systemstack and there is no CALL
   292  			// instruction to look for at pc - 1
   293  		default:
   294  			r.lastpc = it.pc - 1
   295  			r.Call.File, r.Call.Line = r.Current.Fn.cu.lineInfo.PCToLine(r.Current.Fn.Entry, it.pc-1)
   296  		}
   297  	}
   298  	return r
   299  }
   300  
   301  func (it *stackIterator) stacktrace(depth int) ([]Stackframe, error) {
   302  	if depth < 0 {
   303  		return nil, errors.New("negative maximum stack depth")
   304  	}
   305  	if it.opts&StacktraceG != 0 && it.g != nil {
   306  		it.switchToGoroutineStack()
   307  		it.top = true
   308  	}
   309  	frames := make([]Stackframe, 0, depth+1)
   310  	for it.Next() {
   311  		frames = it.appendInlineCalls(frames, it.Frame())
   312  		if len(frames) >= depth+1 {
   313  			break
   314  		}
   315  	}
   316  	if err := it.Err(); err != nil {
   317  		if len(frames) == 0 {
   318  			return nil, err
   319  		}
   320  		frames = append(frames, Stackframe{Err: err})
   321  	}
   322  	return frames, nil
   323  }
   324  
   325  func (it *stackIterator) appendInlineCalls(frames []Stackframe, frame Stackframe) []Stackframe {
   326  	if frame.Call.Fn == nil {
   327  		return append(frames, frame)
   328  	}
   329  	if frame.Call.Fn.cu.lineInfo == nil {
   330  		return append(frames, frame)
   331  	}
   332  
   333  	callpc := frame.Call.PC
   334  	if len(frames) > 0 {
   335  		callpc--
   336  	}
   337  
   338  	dwarfTree, err := frame.Call.Fn.cu.image.getDwarfTree(frame.Call.Fn.offset)
   339  	if err != nil {
   340  		return append(frames, frame)
   341  	}
   342  
   343  	for _, entry := range reader.InlineStack(dwarfTree, callpc) {
   344  		fnname, okname := entry.Val(dwarf.AttrName).(string)
   345  		fileidx, okfileidx := entry.Val(dwarf.AttrCallFile).(int64)
   346  		line, okline := entry.Val(dwarf.AttrCallLine).(int64)
   347  
   348  		if !okname || !okfileidx || !okline {
   349  			break
   350  		}
   351  		var e *dwarf.Entry
   352  		filepath, fileErr := frame.Current.Fn.cu.filePath(int(fileidx), e)
   353  		if fileErr != nil {
   354  			break
   355  		}
   356  
   357  		inlfn := &Function{Name: fnname, Entry: frame.Call.Fn.Entry, End: frame.Call.Fn.End, offset: entry.Offset, cu: frame.Call.Fn.cu}
   358  		frames = append(frames, Stackframe{
   359  			Current: frame.Current,
   360  			Call: Location{
   361  				frame.Call.PC,
   362  				frame.Call.File,
   363  				frame.Call.Line,
   364  				inlfn,
   365  			},
   366  			Regs:        frame.Regs,
   367  			stackHi:     frame.stackHi,
   368  			Ret:         frame.Ret,
   369  			addrret:     frame.addrret,
   370  			Err:         frame.Err,
   371  			SystemStack: frame.SystemStack,
   372  			Inlined:     true,
   373  			lastpc:      frame.lastpc,
   374  		})
   375  
   376  		frame.Call.File = filepath
   377  		frame.Call.Line = int(line)
   378  	}
   379  
   380  	return append(frames, frame)
   381  }
   382  
   383  // advanceRegs calculates the DwarfRegisters for a next stack frame
   384  // (corresponding to it.pc).
   385  //
   386  // The computation uses the registers for the current stack frame (it.regs) and
   387  // the corresponding Frame Descriptor Entry (FDE) retrieved from the DWARF info.
   388  //
   389  // The new set of registers is returned. it.regs is not updated, except for
   390  // it.regs.CFA; the caller has to eventually switch it.regs when the iterator
   391  // advances to the next frame.
   392  func (it *stackIterator) advanceRegs() (callFrameRegs op.DwarfRegisters, ret uint64, retaddr uint64) {
   393  	fde, err := it.bi.frameEntries.FDEForPC(it.pc)
   394  	var framectx *frame.FrameContext
   395  	if _, nofde := err.(*frame.ErrNoFDEForPC); nofde {
   396  		framectx = it.bi.Arch.fixFrameUnwindContext(nil, it.pc, it.bi)
   397  	} else {
   398  		framectx = it.bi.Arch.fixFrameUnwindContext(fde.EstablishFrame(it.pc), it.pc, it.bi)
   399  	}
   400  
   401  	cfareg, err := it.executeFrameRegRule(0, framectx.CFA, 0)
   402  	if cfareg == nil {
   403  		it.err = fmt.Errorf("CFA becomes undefined at PC %#x: %v", it.pc, err)
   404  		return op.DwarfRegisters{}, 0, 0
   405  	}
   406  	it.regs.CFA = int64(cfareg.Uint64Val)
   407  
   408  	callimage := it.bi.PCToImage(it.pc)
   409  
   410  	callFrameRegs = op.DwarfRegisters{StaticBase: callimage.StaticBase, ByteOrder: it.regs.ByteOrder, PCRegNum: it.regs.PCRegNum, SPRegNum: it.regs.SPRegNum, BPRegNum: it.regs.BPRegNum, LRRegNum: it.regs.LRRegNum}
   411  
   412  	// According to the standard the compiler should be responsible for emitting
   413  	// rules for the RSP register so that it can then be used to calculate CFA,
   414  	// however neither Go nor GCC do this.
   415  	// In the following line we copy GDB's behaviour by assuming this is
   416  	// implicit.
   417  	// See also the comment in dwarf2_frame_default_init in
   418  	// $GDB_SOURCE/dwarf2-frame.c
   419  	callFrameRegs.AddReg(callFrameRegs.SPRegNum, cfareg)
   420  
   421  	for i, regRule := range framectx.Regs {
   422  		reg, err := it.executeFrameRegRule(i, regRule, it.regs.CFA)
   423  		callFrameRegs.AddReg(i, reg)
   424  		if i == framectx.RetAddrReg {
   425  			if reg == nil {
   426  				if err == nil {
   427  					//lint:ignore ST1005 backwards compatibility
   428  					err = fmt.Errorf("Undefined return address at %#x", it.pc)
   429  				}
   430  				it.err = err
   431  			} else {
   432  				ret = reg.Uint64Val
   433  			}
   434  			retaddr = uint64(it.regs.CFA + regRule.Offset)
   435  		}
   436  	}
   437  
   438  	if it.bi.Arch.Name == "arm64" {
   439  		if ret == 0 && it.regs.Reg(it.regs.LRRegNum) != nil {
   440  			ret = it.regs.Reg(it.regs.LRRegNum).Uint64Val
   441  		}
   442  	}
   443  
   444  	return callFrameRegs, ret, retaddr
   445  }
   446  
   447  func (it *stackIterator) executeFrameRegRule(regnum uint64, rule frame.DWRule, cfa int64) (*op.DwarfRegister, error) {
   448  	switch rule.Rule {
   449  	default:
   450  		fallthrough
   451  	case frame.RuleUndefined:
   452  		return nil, nil
   453  	case frame.RuleSameVal:
   454  		if it.regs.Reg(regnum) == nil {
   455  			return nil, nil
   456  		}
   457  		reg := *it.regs.Reg(regnum)
   458  		return &reg, nil
   459  	case frame.RuleOffset:
   460  		return it.readRegisterAt(regnum, uint64(cfa+rule.Offset))
   461  	case frame.RuleValOffset:
   462  		return op.DwarfRegisterFromUint64(uint64(cfa + rule.Offset)), nil
   463  	case frame.RuleRegister:
   464  		return it.regs.Reg(rule.Reg), nil
   465  	case frame.RuleExpression:
   466  		v, _, err := op.ExecuteStackProgram(it.regs, rule.Expression, it.bi.Arch.PtrSize(), it.mem.ReadMemory)
   467  		if err != nil {
   468  			return nil, err
   469  		}
   470  		return it.readRegisterAt(regnum, uint64(v))
   471  	case frame.RuleValExpression:
   472  		v, _, err := op.ExecuteStackProgram(it.regs, rule.Expression, it.bi.Arch.PtrSize(), it.mem.ReadMemory)
   473  		if err != nil {
   474  			return nil, err
   475  		}
   476  		return op.DwarfRegisterFromUint64(uint64(v)), nil
   477  	case frame.RuleArchitectural:
   478  		return nil, errors.New("architectural frame rules are unsupported")
   479  	case frame.RuleCFA:
   480  		if it.regs.Reg(rule.Reg) == nil {
   481  			return nil, nil
   482  		}
   483  		return op.DwarfRegisterFromUint64(uint64(int64(it.regs.Uint64Val(rule.Reg)) + rule.Offset)), nil
   484  	case frame.RuleFramePointer:
   485  		curReg := it.regs.Reg(rule.Reg)
   486  		if curReg == nil {
   487  			return nil, nil
   488  		}
   489  		if curReg.Uint64Val <= uint64(cfa) {
   490  			return it.readRegisterAt(regnum, curReg.Uint64Val)
   491  		}
   492  		newReg := *curReg
   493  		return &newReg, nil
   494  	}
   495  }
   496  
   497  func (it *stackIterator) readRegisterAt(regnum uint64, addr uint64) (*op.DwarfRegister, error) {
   498  	buf := make([]byte, it.bi.Arch.regSize(regnum))
   499  	_, err := it.mem.ReadMemory(buf, addr)
   500  	if err != nil {
   501  		return nil, err
   502  	}
   503  	return op.DwarfRegisterFromBytes(buf), nil
   504  }
   505  
   506  func (it *stackIterator) loadG0SchedSP() {
   507  	if it.g0_sched_sp_loaded {
   508  		return
   509  	}
   510  	it.g0_sched_sp_loaded = true
   511  	if it.g != nil {
   512  		mvar, _ := it.g.variable.structMember("m")
   513  		if mvar != nil {
   514  			g0var, _ := mvar.structMember("g0")
   515  			if g0var != nil {
   516  				g0, _ := g0var.parseG()
   517  				if g0 != nil {
   518  					it.g0_sched_sp = g0.SP
   519  				}
   520  			}
   521  		}
   522  	}
   523  }
   524  
   525  // Defer represents one deferred call
   526  type Defer struct {
   527  	DwrapPC uint64 // PC of the deferred function or, in Go 1.17+ a wrapper to it
   528  	DeferPC uint64 // PC address of instruction that added this defer
   529  	SP      uint64 // Value of SP register when this function was deferred (this field gets adjusted when the stack is moved to match the new stack space)
   530  	link    *Defer // Next deferred function
   531  	argSz   int64  // Always 0 in Go >=1.17
   532  
   533  	variable   *Variable
   534  	Unreadable error
   535  }
   536  
   537  // readDefers decorates the frames with the function deferred at each stack frame.
   538  func (g *G) readDefers(frames []Stackframe) {
   539  	curdefer := g.Defer()
   540  	i := 0
   541  
   542  	// scan simultaneously frames and the curdefer linked list, assigning
   543  	// defers to their associated frames.
   544  	for {
   545  		if curdefer == nil || i >= len(frames) {
   546  			return
   547  		}
   548  		if curdefer.Unreadable != nil {
   549  			// Current defer is unreadable, stick it into the first available frame
   550  			// (so that it can be reported to the user) and exit
   551  			frames[i].Defers = append(frames[i].Defers, curdefer)
   552  			return
   553  		}
   554  		if frames[i].Err != nil {
   555  			return
   556  		}
   557  
   558  		if frames[i].TopmostDefer == nil {
   559  			frames[i].TopmostDefer = curdefer
   560  		}
   561  
   562  		if frames[i].SystemStack || curdefer.SP >= uint64(frames[i].Regs.CFA) {
   563  			// frames[i].Regs.CFA is the value that SP had before the function of
   564  			// frames[i] was called.
   565  			// This means that when curdefer.SP == frames[i].Regs.CFA then curdefer
   566  			// was added by the previous frame.
   567  			//
   568  			// curdefer.SP < frames[i].Regs.CFA means curdefer was added by a
   569  			// function further down the stack.
   570  			//
   571  			// SystemStack frames live on a different physical stack and can't be
   572  			// compared with deferred frames.
   573  			i++
   574  		} else {
   575  			frames[i].Defers = append(frames[i].Defers, curdefer)
   576  			curdefer = curdefer.Next()
   577  		}
   578  	}
   579  }
   580  
   581  func (d *Defer) load() {
   582  	v := d.variable // +rtype _defer
   583  	v.loadValue(LoadConfig{false, 1, 0, 0, -1, 0})
   584  	if v.Unreadable != nil {
   585  		d.Unreadable = v.Unreadable
   586  		return
   587  	}
   588  
   589  	fnvar := v.fieldVariable("fn")
   590  	if fnvar.Kind == reflect.Func {
   591  		// In Go 1.18, fn is a func().
   592  		d.DwrapPC = fnvar.Base
   593  	} else if val := fnvar.maybeDereference(); val.Addr != 0 {
   594  		// In Go <1.18, fn is a *funcval.
   595  		fnvar = fnvar.loadFieldNamed("fn")
   596  		if fnvar.Unreadable == nil {
   597  			d.DwrapPC, _ = constant.Uint64Val(fnvar.Value)
   598  		}
   599  	}
   600  
   601  	d.DeferPC, _ = constant.Uint64Val(v.fieldVariable("pc").Value) // +rtype uintptr
   602  	d.SP, _ = constant.Uint64Val(v.fieldVariable("sp").Value)      // +rtype uintptr
   603  	sizVar := v.fieldVariable("siz")                               // +rtype -opt int32
   604  	if sizVar != nil {
   605  		// In Go <1.18, siz stores the number of bytes of
   606  		// defer arguments following the defer record. In Go
   607  		// 1.18, the defer record doesn't store arguments, so
   608  		// we leave this 0.
   609  		d.argSz, _ = constant.Int64Val(sizVar.Value)
   610  	}
   611  
   612  	linkvar := v.fieldVariable("link").maybeDereference() // +rtype *_defer
   613  	if linkvar.Addr != 0 {
   614  		d.link = &Defer{variable: linkvar}
   615  	}
   616  }
   617  
   618  // errSPDecreased is used when (*Defer).Next detects a corrupted linked
   619  // list, specifically when after followin a link pointer the value of SP
   620  // decreases rather than increasing or staying the same (the defer list is a
   621  // FIFO list, nodes further down the list have been added by function calls
   622  // further down the call stack and therefore the SP should always increase).
   623  var errSPDecreased = errors.New("corrupted defer list: SP decreased")
   624  
   625  // Next returns the next defer in the linked list
   626  func (d *Defer) Next() *Defer {
   627  	if d.link == nil {
   628  		return nil
   629  	}
   630  	d.link.load()
   631  	if d.link.SP < d.SP {
   632  		d.link.Unreadable = errSPDecreased
   633  	}
   634  	return d.link
   635  }
   636  
   637  // EvalScope returns an EvalScope relative to the argument frame of this deferred call.
   638  // The argument frame of a deferred call is stored in memory immediately
   639  // after the deferred header.
   640  func (d *Defer) EvalScope(t *Target, thread Thread) (*EvalScope, error) {
   641  	scope, err := GoroutineScope(t, thread)
   642  	if err != nil {
   643  		return nil, fmt.Errorf("could not get scope: %v", err)
   644  	}
   645  
   646  	bi := thread.BinInfo()
   647  	scope.PC = d.DwrapPC
   648  	scope.File, scope.Line, scope.Fn = bi.PCToLine(d.DwrapPC)
   649  
   650  	if scope.Fn == nil {
   651  		return nil, fmt.Errorf("could not find function at %#x", d.DwrapPC)
   652  	}
   653  
   654  	// The arguments are stored immediately after the defer header struct, i.e.
   655  	// addr+sizeof(_defer).
   656  
   657  	if !bi.Arch.usesLR {
   658  		// On architectures that don't have a link register CFA is always the address of the first
   659  		// argument, that's what we use for the value of CFA.
   660  		// For SP we use CFA minus the size of one pointer because that would be
   661  		// the space occupied by pushing the return address on the stack during the
   662  		// CALL.
   663  		scope.Regs.CFA = (int64(d.variable.Addr) + d.variable.RealType.Common().ByteSize)
   664  		scope.Regs.Reg(scope.Regs.SPRegNum).Uint64Val = uint64(scope.Regs.CFA - int64(bi.Arch.PtrSize()))
   665  	} else {
   666  		// On architectures that have a link register CFA and SP have the same
   667  		// value but the address of the first argument is at CFA+ptrSize so we set
   668  		// CFA to the start of the argument frame minus one pointer size.
   669  		scope.Regs.CFA = int64(d.variable.Addr) + d.variable.RealType.Common().ByteSize - int64(bi.Arch.PtrSize())
   670  		scope.Regs.Reg(scope.Regs.SPRegNum).Uint64Val = uint64(scope.Regs.CFA)
   671  	}
   672  
   673  	rdr := scope.Fn.cu.image.dwarfReader
   674  	rdr.Seek(scope.Fn.offset)
   675  	e, err := rdr.Next()
   676  	if err != nil {
   677  		return nil, fmt.Errorf("could not read DWARF function entry: %v", err)
   678  	}
   679  	scope.Regs.FrameBase, _, _, _ = bi.Location(e, dwarf.AttrFrameBase, scope.PC, scope.Regs, scope.Mem)
   680  	scope.Mem = cacheMemory(scope.Mem, uint64(scope.Regs.CFA), int(d.argSz))
   681  
   682  	return scope, nil
   683  }
   684  
   685  // DeferredFunc returns the deferred function, on Go 1.17 and later unwraps
   686  // any defer wrapper.
   687  func (d *Defer) DeferredFunc(p *Target) (file string, line int, fn *Function) {
   688  	bi := p.BinInfo()
   689  	fn = bi.PCToFunc(d.DwrapPC)
   690  	fn = p.dwrapUnwrap(fn)
   691  	if fn == nil {
   692  		return "", 0, nil
   693  	}
   694  	file, line = fn.cu.lineInfo.PCToLine(fn.Entry, fn.Entry)
   695  	return file, line, fn
   696  }