mirror of
				https://github.com/go-delve/delve.git
				synced 2025-10-31 10:47:27 +08:00 
			
		
		
		
	
		
			
				
	
	
		
			184 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			184 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package op
 | |
| 
 | |
| import (
 | |
| 	"bytes"
 | |
| 	"encoding/binary"
 | |
| )
 | |
| 
 | |
| // DwarfRegisters holds the value of stack program registers.
 | |
| type DwarfRegisters struct {
 | |
| 	StaticBase uint64
 | |
| 
 | |
| 	CFA       int64
 | |
| 	FrameBase int64
 | |
| 	ObjBase   int64
 | |
| 	regs      []*DwarfRegister
 | |
| 
 | |
| 	ByteOrder  binary.ByteOrder
 | |
| 	PCRegNum   uint64
 | |
| 	SPRegNum   uint64
 | |
| 	BPRegNum   uint64
 | |
| 	LRRegNum   uint64
 | |
| 	ChangeFunc RegisterChangeFunc
 | |
| 
 | |
| 	FloatLoadError   error // error produced when loading floating point registers
 | |
| 	loadMoreCallback func()
 | |
| }
 | |
| 
 | |
| type DwarfRegister struct {
 | |
| 	Uint64Val uint64
 | |
| 	Bytes     []byte
 | |
| }
 | |
| 
 | |
| type RegisterChangeFunc func(regNum uint64, reg *DwarfRegister) error
 | |
| 
 | |
| // NewDwarfRegisters returns a new DwarfRegisters object.
 | |
| func NewDwarfRegisters(staticBase uint64, regs []*DwarfRegister, byteOrder binary.ByteOrder, pcRegNum, spRegNum, bpRegNum, lrRegNum uint64) *DwarfRegisters {
 | |
| 	return &DwarfRegisters{
 | |
| 		StaticBase: staticBase,
 | |
| 		regs:       regs,
 | |
| 		ByteOrder:  byteOrder,
 | |
| 		PCRegNum:   pcRegNum,
 | |
| 		SPRegNum:   spRegNum,
 | |
| 		BPRegNum:   bpRegNum,
 | |
| 		LRRegNum:   lrRegNum,
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // SetLoadMoreCallback sets a callback function that will be called the
 | |
| // first time the user of regs tries to access an undefined register.
 | |
| func (regs *DwarfRegisters) SetLoadMoreCallback(fn func()) {
 | |
| 	regs.loadMoreCallback = fn
 | |
| }
 | |
| 
 | |
| // CurrentSize returns the current number of known registers. This number might be
 | |
| // wrong if loadMoreCallback has been set.
 | |
| func (regs *DwarfRegisters) CurrentSize() int {
 | |
| 	return len(regs.regs)
 | |
| }
 | |
| 
 | |
| // Uint64Val returns the uint64 value of register idx.
 | |
| func (regs *DwarfRegisters) Uint64Val(idx uint64) uint64 {
 | |
| 	reg := regs.Reg(idx)
 | |
| 	if reg == nil {
 | |
| 		return 0
 | |
| 	}
 | |
| 	return regs.regs[idx].Uint64Val
 | |
| }
 | |
| 
 | |
| // Bytes returns the bytes value of register idx, nil if the register is not
 | |
| // defined.
 | |
| func (regs *DwarfRegisters) Bytes(idx uint64) []byte {
 | |
| 	reg := regs.Reg(idx)
 | |
| 	if reg == nil {
 | |
| 		return nil
 | |
| 	}
 | |
| 	if reg.Bytes == nil {
 | |
| 		var buf bytes.Buffer
 | |
| 		binary.Write(&buf, regs.ByteOrder, reg.Uint64Val)
 | |
| 		reg.Bytes = buf.Bytes()
 | |
| 	}
 | |
| 	return reg.Bytes
 | |
| }
 | |
| 
 | |
| func (regs *DwarfRegisters) loadMore() {
 | |
| 	if regs.loadMoreCallback == nil {
 | |
| 		return
 | |
| 	}
 | |
| 	regs.loadMoreCallback()
 | |
| 	regs.loadMoreCallback = nil
 | |
| }
 | |
| 
 | |
| // Reg returns register idx or nil if the register is not defined.
 | |
| func (regs *DwarfRegisters) Reg(idx uint64) *DwarfRegister {
 | |
| 	if idx >= uint64(len(regs.regs)) {
 | |
| 		regs.loadMore()
 | |
| 		if idx >= uint64(len(regs.regs)) {
 | |
| 			return nil
 | |
| 		}
 | |
| 	}
 | |
| 	if regs.regs[idx] == nil {
 | |
| 		regs.loadMore()
 | |
| 	}
 | |
| 	return regs.regs[idx]
 | |
| }
 | |
| 
 | |
| func (regs *DwarfRegisters) PC() uint64 {
 | |
| 	return regs.Uint64Val(regs.PCRegNum)
 | |
| }
 | |
| 
 | |
| func (regs *DwarfRegisters) SP() uint64 {
 | |
| 	return regs.Uint64Val(regs.SPRegNum)
 | |
| }
 | |
| 
 | |
| func (regs *DwarfRegisters) BP() uint64 {
 | |
| 	return regs.Uint64Val(regs.BPRegNum)
 | |
| }
 | |
| 
 | |
| // AddReg adds register idx to regs.
 | |
| func (regs *DwarfRegisters) AddReg(idx uint64, reg *DwarfRegister) {
 | |
| 	if idx >= uint64(len(regs.regs)) {
 | |
| 		newRegs := make([]*DwarfRegister, idx+1)
 | |
| 		copy(newRegs, regs.regs)
 | |
| 		regs.regs = newRegs
 | |
| 	}
 | |
| 	regs.regs[idx] = reg
 | |
| }
 | |
| 
 | |
| // ClearRegisters clears all registers.
 | |
| func (regs *DwarfRegisters) ClearRegisters() {
 | |
| 	regs.loadMoreCallback = nil
 | |
| 	for regnum := range regs.regs {
 | |
| 		regs.regs[regnum] = nil
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func DwarfRegisterFromUint64(v uint64) *DwarfRegister {
 | |
| 	return &DwarfRegister{Uint64Val: v}
 | |
| }
 | |
| 
 | |
| func DwarfRegisterFromBytes(bytes []byte) *DwarfRegister {
 | |
| 	var v uint64
 | |
| 	switch len(bytes) {
 | |
| 	case 1:
 | |
| 		v = uint64(bytes[0])
 | |
| 	case 2:
 | |
| 		x := binary.LittleEndian.Uint16(bytes)
 | |
| 		v = uint64(x)
 | |
| 	case 4:
 | |
| 		x := binary.LittleEndian.Uint32(bytes)
 | |
| 		v = uint64(x)
 | |
| 	default:
 | |
| 		if len(bytes) >= 8 {
 | |
| 			v = binary.LittleEndian.Uint64(bytes[:8])
 | |
| 		}
 | |
| 	}
 | |
| 	return &DwarfRegister{Uint64Val: v, Bytes: bytes}
 | |
| }
 | |
| 
 | |
| // FillBytes fills the Bytes slice of reg using Uint64Val.
 | |
| func (reg *DwarfRegister) FillBytes() {
 | |
| 	if reg.Bytes != nil {
 | |
| 		return
 | |
| 	}
 | |
| 	reg.Bytes = make([]byte, 8)
 | |
| 	binary.LittleEndian.PutUint64(reg.Bytes, reg.Uint64Val)
 | |
| }
 | |
| 
 | |
| // Overwrite takes the contents of reg and overwrites them with the contents
 | |
| // of reg2 in little-endian order, returning a new register. The new register
 | |
| // will always contain the complete contents of both registers, so if reg2 is
 | |
| // larger than reg, the final register will be reg2's size.
 | |
| func (reg *DwarfRegister) Overwrite(reg2 *DwarfRegister) *DwarfRegister {
 | |
| 	reg.FillBytes()
 | |
| 	reg2.FillBytes()
 | |
| 	width := len(reg.Bytes)
 | |
| 	if len(reg2.Bytes) > len(reg.Bytes) {
 | |
| 		width = len(reg2.Bytes)
 | |
| 	}
 | |
| 	b := make([]byte, width)
 | |
| 	copy(b, reg.Bytes)
 | |
| 	copy(b, reg2.Bytes)
 | |
| 	return DwarfRegisterFromBytes(b)
 | |
| }
 | 
