package op import ( "bytes" "encoding/binary" ) type DwarfRegisters struct { StaticBase uint64 CFA int64 FrameBase int64 ObjBase int64 Regs []*DwarfRegister ByteOrder binary.ByteOrder PCRegNum uint64 SPRegNum uint64 BPRegNum uint64 } type DwarfRegister struct { Uint64Val uint64 Bytes []byte } // 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 } // 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)) { return nil } 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 } 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} }