github.com/undoio/delve@v1.9.0/pkg/dwarf/op/regs.go (about)

     1  package op
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/binary"
     6  )
     7  
     8  // DwarfRegisters holds the value of stack program registers.
     9  type DwarfRegisters struct {
    10  	StaticBase uint64
    11  
    12  	CFA       int64
    13  	FrameBase int64
    14  	ObjBase   int64
    15  	regs      []*DwarfRegister
    16  
    17  	ByteOrder  binary.ByteOrder
    18  	PCRegNum   uint64
    19  	SPRegNum   uint64
    20  	BPRegNum   uint64
    21  	LRRegNum   uint64
    22  	ChangeFunc RegisterChangeFunc
    23  
    24  	FloatLoadError   error // error produced when loading floating point registers
    25  	loadMoreCallback func()
    26  }
    27  
    28  type DwarfRegister struct {
    29  	Uint64Val uint64
    30  	Bytes     []byte
    31  }
    32  
    33  type RegisterChangeFunc func(regNum uint64, reg *DwarfRegister) error
    34  
    35  // NewDwarfRegisters returns a new DwarfRegisters object.
    36  func NewDwarfRegisters(staticBase uint64, regs []*DwarfRegister, byteOrder binary.ByteOrder, pcRegNum, spRegNum, bpRegNum, lrRegNum uint64) *DwarfRegisters {
    37  	return &DwarfRegisters{
    38  		StaticBase: staticBase,
    39  		regs:       regs,
    40  		ByteOrder:  byteOrder,
    41  		PCRegNum:   pcRegNum,
    42  		SPRegNum:   spRegNum,
    43  		BPRegNum:   bpRegNum,
    44  		LRRegNum:   lrRegNum,
    45  	}
    46  }
    47  
    48  // SetLoadMoreCallback sets a callback function that will be called the
    49  // first time the user of regs tries to access an undefined register.
    50  func (regs *DwarfRegisters) SetLoadMoreCallback(fn func()) {
    51  	regs.loadMoreCallback = fn
    52  }
    53  
    54  // CurrentSize returns the current number of known registers. This number might be
    55  // wrong if loadMoreCallback has been set.
    56  func (regs *DwarfRegisters) CurrentSize() int {
    57  	return len(regs.regs)
    58  }
    59  
    60  // Uint64Val returns the uint64 value of register idx.
    61  func (regs *DwarfRegisters) Uint64Val(idx uint64) uint64 {
    62  	reg := regs.Reg(idx)
    63  	if reg == nil {
    64  		return 0
    65  	}
    66  	return regs.regs[idx].Uint64Val
    67  }
    68  
    69  // Bytes returns the bytes value of register idx, nil if the register is not
    70  // defined.
    71  func (regs *DwarfRegisters) Bytes(idx uint64) []byte {
    72  	reg := regs.Reg(idx)
    73  	if reg == nil {
    74  		return nil
    75  	}
    76  	if reg.Bytes == nil {
    77  		var buf bytes.Buffer
    78  		binary.Write(&buf, regs.ByteOrder, reg.Uint64Val)
    79  		reg.Bytes = buf.Bytes()
    80  	}
    81  	return reg.Bytes
    82  }
    83  
    84  func (regs *DwarfRegisters) loadMore() {
    85  	if regs.loadMoreCallback == nil {
    86  		return
    87  	}
    88  	regs.loadMoreCallback()
    89  	regs.loadMoreCallback = nil
    90  }
    91  
    92  // Reg returns register idx or nil if the register is not defined.
    93  func (regs *DwarfRegisters) Reg(idx uint64) *DwarfRegister {
    94  	if idx >= uint64(len(regs.regs)) {
    95  		regs.loadMore()
    96  		if idx >= uint64(len(regs.regs)) {
    97  			return nil
    98  		}
    99  	}
   100  	if regs.regs[idx] == nil {
   101  		regs.loadMore()
   102  	}
   103  	return regs.regs[idx]
   104  }
   105  
   106  func (regs *DwarfRegisters) PC() uint64 {
   107  	return regs.Uint64Val(regs.PCRegNum)
   108  }
   109  
   110  func (regs *DwarfRegisters) SP() uint64 {
   111  	return regs.Uint64Val(regs.SPRegNum)
   112  }
   113  
   114  func (regs *DwarfRegisters) BP() uint64 {
   115  	return regs.Uint64Val(regs.BPRegNum)
   116  }
   117  
   118  // AddReg adds register idx to regs.
   119  func (regs *DwarfRegisters) AddReg(idx uint64, reg *DwarfRegister) {
   120  	if idx >= uint64(len(regs.regs)) {
   121  		newRegs := make([]*DwarfRegister, idx+1)
   122  		copy(newRegs, regs.regs)
   123  		regs.regs = newRegs
   124  	}
   125  	regs.regs[idx] = reg
   126  }
   127  
   128  // ClearRegisters clears all registers.
   129  func (regs *DwarfRegisters) ClearRegisters() {
   130  	regs.loadMoreCallback = nil
   131  	for regnum := range regs.regs {
   132  		regs.regs[regnum] = nil
   133  	}
   134  }
   135  
   136  func DwarfRegisterFromUint64(v uint64) *DwarfRegister {
   137  	return &DwarfRegister{Uint64Val: v}
   138  }
   139  
   140  func DwarfRegisterFromBytes(bytes []byte) *DwarfRegister {
   141  	var v uint64
   142  	switch len(bytes) {
   143  	case 1:
   144  		v = uint64(bytes[0])
   145  	case 2:
   146  		x := binary.LittleEndian.Uint16(bytes)
   147  		v = uint64(x)
   148  	case 4:
   149  		x := binary.LittleEndian.Uint32(bytes)
   150  		v = uint64(x)
   151  	default:
   152  		if len(bytes) >= 8 {
   153  			v = binary.LittleEndian.Uint64(bytes[:8])
   154  		}
   155  	}
   156  	return &DwarfRegister{Uint64Val: v, Bytes: bytes}
   157  }
   158  
   159  // FillBytes fills the Bytes slice of reg using Uint64Val.
   160  func (reg *DwarfRegister) FillBytes() {
   161  	if reg.Bytes != nil {
   162  		return
   163  	}
   164  	reg.Bytes = make([]byte, 8)
   165  	binary.LittleEndian.PutUint64(reg.Bytes, reg.Uint64Val)
   166  }
   167  
   168  // Overwrite takes the contents of reg1 and overwrites them with the contents
   169  // of reg2 in little-endian order, returning a new register. The new register
   170  // will always contain the complete contents of both registers, so if reg2 is
   171  // larger than reg1, the final register will be reg2's size.
   172  func (reg1 *DwarfRegister) Overwrite(reg2 *DwarfRegister) *DwarfRegister {
   173  	reg1.FillBytes()
   174  	reg2.FillBytes()
   175  	width := len(reg1.Bytes)
   176  	if len(reg2.Bytes) > len(reg1.Bytes) {
   177  		width = len(reg2.Bytes)
   178  	}
   179  	b := make([]byte, width)
   180  	copy(b, reg1.Bytes)
   181  	copy(b, reg2.Bytes)
   182  	return DwarfRegisterFromBytes(b)
   183  }