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 }