gitlab.com/Raven-IO/raven-delve@v1.22.4/pkg/proc/linutil/regs_ppc64le_arch.go (about)

     1  package linutil
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"gitlab.com/Raven-IO/raven-delve/pkg/dwarf/op"
     7  	"gitlab.com/Raven-IO/raven-delve/pkg/dwarf/regnum"
     8  	"gitlab.com/Raven-IO/raven-delve/pkg/proc"
     9  )
    10  
    11  // PPC64LERegisters implements the proc.Registers interface for the native/linux
    12  // backend and core/linux backends, on PPC64LE.
    13  type PPC64LERegisters struct {
    14  	Regs       *PPC64LEPtraceRegs
    15  	Fpregs     []proc.Register //Formatted floating point registers
    16  	Fpregset   []byte          //holding all floating point register values
    17  	loadFpRegs func(*PPC64LERegisters) error
    18  }
    19  
    20  func NewPPC64LERegisters(regs *PPC64LEPtraceRegs, loadFpRegs func(*PPC64LERegisters) error) *PPC64LERegisters {
    21  	return &PPC64LERegisters{Regs: regs, loadFpRegs: loadFpRegs}
    22  }
    23  
    24  // PPC64LEPtraceRegs is the struct used by the linux kernel to return the
    25  // general purpose registers for PPC64LE CPUs.
    26  // Copied from src/syscall/ztypes_linux_ppc64le.go#L518-L532
    27  type PPC64LEPtraceRegs struct {
    28  	Gpr       [32]uint64 // 32 general-purpose registers, each 64 bits wide
    29  	Nip       uint64
    30  	Msr       uint64
    31  	Orig_gpr3 uint64
    32  	Ctr       uint64
    33  	Link      uint64 // Link register -- LLDB dwarf_lr_ppc64le = 65
    34  	Xer       uint64 // Fixed point exception register -- LLDB dwarf_xer_ppc64le = 76
    35  	Ccr       uint64
    36  	Softe     uint64
    37  	Trap      uint64
    38  	Dar       uint64
    39  	Dsisr     uint64
    40  	Result    uint64
    41  }
    42  
    43  // PC returns the value of the NIP register
    44  // Also called the IAR/Instruction Address Register or NIP/Next Instruction Pointer
    45  func (r *PPC64LERegisters) PC() uint64 {
    46  	return r.Regs.Nip
    47  }
    48  
    49  // SP returns the value of Stack frame pointer stored in Gpr[1].
    50  func (r *PPC64LERegisters) SP() uint64 {
    51  	return r.Regs.Gpr[1]
    52  }
    53  
    54  // LR The Link Register is a 64-bit register. It can be
    55  // used to provide the branch target address for the
    56  // Branch Conditional to Link Register instruction, and it
    57  // holds the return address after Branch instructions for
    58  // which LK=1 and after System Call Vectored instructions.
    59  // Extracted from the 2.3.2 section of the PowerISA Book 3.1
    60  func (r *PPC64LERegisters) LR() uint64 {
    61  	return r.Regs.Link
    62  }
    63  
    64  func (r *PPC64LERegisters) BP() uint64 {
    65  	return r.Regs.Gpr[1]
    66  }
    67  
    68  // TLS returns the value of the thread pointer stored in Gpr[13]
    69  func (r *PPC64LERegisters) TLS() uint64 {
    70  	return r.Regs.Gpr[13]
    71  }
    72  
    73  // GAddr returns the address of the G variable
    74  func (r *PPC64LERegisters) GAddr() (uint64, bool) {
    75  	return r.Regs.Gpr[30], true
    76  }
    77  
    78  // Slice returns the registers as a list of (name, value) pairs.
    79  func (r *PPC64LERegisters) Slice(floatingPoint bool) ([]proc.Register, error) {
    80  	var regs = []struct {
    81  		k string
    82  		v uint64
    83  	}{
    84  		{"R0", r.Regs.Gpr[0]},
    85  		{"R1", r.Regs.Gpr[1]},
    86  		{"R2", r.Regs.Gpr[2]},
    87  		{"R3", r.Regs.Gpr[3]},
    88  		{"R4", r.Regs.Gpr[4]},
    89  		{"R5", r.Regs.Gpr[5]},
    90  		{"R6", r.Regs.Gpr[6]},
    91  		{"R7", r.Regs.Gpr[7]},
    92  		{"R8", r.Regs.Gpr[8]},
    93  		{"R9", r.Regs.Gpr[9]},
    94  		{"R10", r.Regs.Gpr[10]},
    95  		{"R11", r.Regs.Gpr[11]},
    96  		{"R12", r.Regs.Gpr[12]},
    97  		{"R13", r.Regs.Gpr[13]},
    98  		{"R14", r.Regs.Gpr[14]},
    99  		{"R15", r.Regs.Gpr[15]},
   100  		{"R16", r.Regs.Gpr[16]},
   101  		{"R17", r.Regs.Gpr[17]},
   102  		{"R18", r.Regs.Gpr[18]},
   103  		{"R19", r.Regs.Gpr[19]},
   104  		{"R20", r.Regs.Gpr[20]},
   105  		{"R21", r.Regs.Gpr[21]},
   106  		{"R22", r.Regs.Gpr[22]},
   107  		{"R23", r.Regs.Gpr[23]},
   108  		{"R24", r.Regs.Gpr[24]},
   109  		{"R25", r.Regs.Gpr[25]},
   110  		{"R26", r.Regs.Gpr[26]},
   111  		{"R27", r.Regs.Gpr[27]},
   112  		{"R28", r.Regs.Gpr[28]},
   113  		{"R29", r.Regs.Gpr[29]},
   114  		{"R30", r.Regs.Gpr[30]},
   115  		{"R31", r.Regs.Gpr[31]},
   116  		{"Nip", r.Regs.Nip},
   117  		{"MSr", r.Regs.Msr},
   118  		{"Orig_gpr3", r.Regs.Orig_gpr3},
   119  		{"Ctr", r.Regs.Ctr},
   120  		{"Link", r.Regs.Link},
   121  		{"Xer", r.Regs.Xer},
   122  		{"Ccr", r.Regs.Ccr},
   123  		{"Softe", r.Regs.Softe},
   124  		{"Trap", r.Regs.Trap},
   125  		{"Dar", r.Regs.Dar},
   126  		{"Dsisr", r.Regs.Dsisr},
   127  		{"Result", r.Regs.Result},
   128  	}
   129  	out := make([]proc.Register, 0, len(regs)+len(r.Fpregs))
   130  	for _, reg := range regs {
   131  		out = proc.AppendUint64Register(out, reg.k, reg.v)
   132  	}
   133  	var floatLoadError error
   134  	if floatingPoint {
   135  		if r.loadFpRegs != nil {
   136  			floatLoadError = r.loadFpRegs(r)
   137  			r.loadFpRegs = nil
   138  		}
   139  		out = append(out, r.Fpregs...)
   140  	}
   141  	return out, floatLoadError
   142  }
   143  
   144  // Copy returns a copy of these registers that is guaranteed not to change.
   145  func (r *PPC64LERegisters) Copy() (proc.Registers, error) {
   146  	if r.loadFpRegs != nil {
   147  		err := r.loadFpRegs(r)
   148  		r.loadFpRegs = nil
   149  		if err != nil {
   150  			return nil, err
   151  		}
   152  	}
   153  	var rr PPC64LERegisters
   154  	rr.Regs = &PPC64LEPtraceRegs{}
   155  	*(rr.Regs) = *(r.Regs)
   156  	if r.Fpregs != nil {
   157  		rr.Fpregs = make([]proc.Register, len(r.Fpregs))
   158  		copy(rr.Fpregs, r.Fpregs)
   159  	}
   160  	if r.Fpregset != nil {
   161  		rr.Fpregset = make([]byte, len(r.Fpregset))
   162  		copy(rr.Fpregset, r.Fpregset)
   163  	}
   164  	return &rr, nil
   165  }
   166  
   167  func (r *PPC64LERegisters) SetReg(regNum uint64, reg *op.DwarfRegister) (fpchanged bool, err error) {
   168  	switch regNum {
   169  	case regnum.PPC64LE_PC:
   170  		r.Regs.Nip = reg.Uint64Val
   171  		return false, nil
   172  	case regnum.PPC64LE_LR:
   173  		r.Regs.Link = reg.Uint64Val
   174  		return false, nil
   175  	case regnum.PPC64LE_SP:
   176  		r.Regs.Gpr[1] = reg.Uint64Val
   177  		return false, nil
   178  	default:
   179  		switch {
   180  		case regNum >= regnum.PPC64LE_R0 && regNum <= regnum.PPC64LE_R0+31:
   181  			r.Regs.Gpr[regNum-regnum.PPC64LE_R0] = reg.Uint64Val
   182  			return false, nil
   183  
   184  		case regNum >= regnum.PPC64LE_F0 && regNum <= regnum.PPC64LE_F0+31:
   185  			if r.loadFpRegs != nil {
   186  				err := r.loadFpRegs(r)
   187  				r.loadFpRegs = nil
   188  				if err != nil {
   189  					return false, err
   190  				}
   191  			}
   192  			// On ppc64le, PPC64LE_VS0 .. PPC64LE_VS31 are mapped onto
   193  			// PPC64LE_F0 .. PPC64LE_F31
   194  			i := regNum - regnum.PPC64LE_VS0
   195  			reg.FillBytes()
   196  			copy(r.Fpregset[8*i:], reg.Bytes)
   197  			return true, nil
   198  
   199  		default:
   200  			return false, fmt.Errorf("changing register %d not implemented", regNum)
   201  		}
   202  	}
   203  }
   204  
   205  type PPC64LEPtraceFpRegs struct {
   206  	Fp []byte
   207  }
   208  
   209  func (fpregs *PPC64LEPtraceFpRegs) Decode() (regs []proc.Register) {
   210  	for i := 0; i < len(fpregs.Fp); i += 8 {
   211  		regs = proc.AppendBytesRegister(regs, fmt.Sprintf("VS%d", i/8), fpregs.Fp[i:i+8])
   212  	}
   213  	return
   214  }