github.com/ttpreport/gvisor-ligolo@v0.0.0-20240123134145-a858404967ba/pkg/sentry/arch/arch_aarch64.go (about)

     1  // Copyright 2020 The gVisor Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  //go:build arm64
    16  // +build arm64
    17  
    18  package arch
    19  
    20  import (
    21  	"fmt"
    22  	"io"
    23  
    24  	"github.com/ttpreport/gvisor-ligolo/pkg/abi/linux"
    25  	"github.com/ttpreport/gvisor-ligolo/pkg/cpuid"
    26  	"github.com/ttpreport/gvisor-ligolo/pkg/errors/linuxerr"
    27  	"github.com/ttpreport/gvisor-ligolo/pkg/sentry/arch/fpu"
    28  	rpb "github.com/ttpreport/gvisor-ligolo/pkg/sentry/arch/registers_go_proto"
    29  )
    30  
    31  // Registers represents the CPU registers for this architecture.
    32  //
    33  // +stateify savable
    34  type Registers struct {
    35  	linux.PtraceRegs
    36  
    37  	// TPIDR_EL0 is the EL0 Read/Write Software Thread ID Register.
    38  	TPIDR_EL0 uint64
    39  }
    40  
    41  const (
    42  	// SyscallWidth is the width of insturctions.
    43  	SyscallWidth = 4
    44  )
    45  
    46  // ARMTrapFlag is the mask for the trap flag.
    47  const ARMTrapFlag = uint64(1) << 21
    48  
    49  // State contains the common architecture bits for aarch64 (the build tag of this
    50  // file ensures it's only built on aarch64).
    51  //
    52  // +stateify savable
    53  type State struct {
    54  	// The system registers.
    55  	Regs Registers
    56  
    57  	// Our floating point state.
    58  	fpState fpu.State `state:"wait"`
    59  
    60  	// OrigR0 stores the value of register R0.
    61  	OrigR0 uint64
    62  }
    63  
    64  // Proto returns a protobuf representation of the system registers in State.
    65  func (s State) Proto() *rpb.Registers {
    66  	regs := &rpb.ARM64Registers{
    67  		R0:     s.Regs.Regs[0],
    68  		R1:     s.Regs.Regs[1],
    69  		R2:     s.Regs.Regs[2],
    70  		R3:     s.Regs.Regs[3],
    71  		R4:     s.Regs.Regs[4],
    72  		R5:     s.Regs.Regs[5],
    73  		R6:     s.Regs.Regs[6],
    74  		R7:     s.Regs.Regs[7],
    75  		R8:     s.Regs.Regs[8],
    76  		R9:     s.Regs.Regs[9],
    77  		R10:    s.Regs.Regs[10],
    78  		R11:    s.Regs.Regs[11],
    79  		R12:    s.Regs.Regs[12],
    80  		R13:    s.Regs.Regs[13],
    81  		R14:    s.Regs.Regs[14],
    82  		R15:    s.Regs.Regs[15],
    83  		R16:    s.Regs.Regs[16],
    84  		R17:    s.Regs.Regs[17],
    85  		R18:    s.Regs.Regs[18],
    86  		R19:    s.Regs.Regs[19],
    87  		R20:    s.Regs.Regs[20],
    88  		R21:    s.Regs.Regs[21],
    89  		R22:    s.Regs.Regs[22],
    90  		R23:    s.Regs.Regs[23],
    91  		R24:    s.Regs.Regs[24],
    92  		R25:    s.Regs.Regs[25],
    93  		R26:    s.Regs.Regs[26],
    94  		R27:    s.Regs.Regs[27],
    95  		R28:    s.Regs.Regs[28],
    96  		R29:    s.Regs.Regs[29],
    97  		R30:    s.Regs.Regs[30],
    98  		Sp:     s.Regs.Sp,
    99  		Pc:     s.Regs.Pc,
   100  		Pstate: s.Regs.Pstate,
   101  		Tls:    s.Regs.TPIDR_EL0,
   102  	}
   103  	return &rpb.Registers{Arch: &rpb.Registers_Arm64{Arm64: regs}}
   104  }
   105  
   106  // Fork creates and returns an identical copy of the state.
   107  func (s *State) Fork() State {
   108  	return State{
   109  		Regs:    s.Regs,
   110  		fpState: s.fpState.Fork(),
   111  		OrigR0:  s.OrigR0,
   112  	}
   113  }
   114  
   115  // StateData implements Context.StateData.
   116  func (s *State) StateData() *State {
   117  	return s
   118  }
   119  
   120  // SingleStep implements Context.SingleStep.
   121  func (s *State) SingleStep() bool {
   122  	return false
   123  }
   124  
   125  // SetSingleStep enables single stepping.
   126  func (s *State) SetSingleStep() {
   127  	// Set the trap flag.
   128  	// TODO(gvisor.dev/issue/1239): ptrace single-step is not supported.
   129  }
   130  
   131  // ClearSingleStep enables single stepping.
   132  func (s *State) ClearSingleStep() {
   133  	// Clear the trap flag.
   134  	// TODO(gvisor.dev/issue/1239): ptrace single-step is not supported.
   135  }
   136  
   137  // RegisterMap returns a map of all registers.
   138  func (s *State) RegisterMap() (map[string]uintptr, error) {
   139  	return map[string]uintptr{
   140  		"R0":     uintptr(s.Regs.Regs[0]),
   141  		"R1":     uintptr(s.Regs.Regs[1]),
   142  		"R2":     uintptr(s.Regs.Regs[2]),
   143  		"R3":     uintptr(s.Regs.Regs[3]),
   144  		"R4":     uintptr(s.Regs.Regs[4]),
   145  		"R5":     uintptr(s.Regs.Regs[5]),
   146  		"R6":     uintptr(s.Regs.Regs[6]),
   147  		"R7":     uintptr(s.Regs.Regs[7]),
   148  		"R8":     uintptr(s.Regs.Regs[8]),
   149  		"R9":     uintptr(s.Regs.Regs[9]),
   150  		"R10":    uintptr(s.Regs.Regs[10]),
   151  		"R11":    uintptr(s.Regs.Regs[11]),
   152  		"R12":    uintptr(s.Regs.Regs[12]),
   153  		"R13":    uintptr(s.Regs.Regs[13]),
   154  		"R14":    uintptr(s.Regs.Regs[14]),
   155  		"R15":    uintptr(s.Regs.Regs[15]),
   156  		"R16":    uintptr(s.Regs.Regs[16]),
   157  		"R17":    uintptr(s.Regs.Regs[17]),
   158  		"R18":    uintptr(s.Regs.Regs[18]),
   159  		"R19":    uintptr(s.Regs.Regs[19]),
   160  		"R20":    uintptr(s.Regs.Regs[20]),
   161  		"R21":    uintptr(s.Regs.Regs[21]),
   162  		"R22":    uintptr(s.Regs.Regs[22]),
   163  		"R23":    uintptr(s.Regs.Regs[23]),
   164  		"R24":    uintptr(s.Regs.Regs[24]),
   165  		"R25":    uintptr(s.Regs.Regs[25]),
   166  		"R26":    uintptr(s.Regs.Regs[26]),
   167  		"R27":    uintptr(s.Regs.Regs[27]),
   168  		"R28":    uintptr(s.Regs.Regs[28]),
   169  		"R29":    uintptr(s.Regs.Regs[29]),
   170  		"R30":    uintptr(s.Regs.Regs[30]),
   171  		"Sp":     uintptr(s.Regs.Sp),
   172  		"Pc":     uintptr(s.Regs.Pc),
   173  		"Pstate": uintptr(s.Regs.Pstate),
   174  		"Tls":    uintptr(s.Regs.TPIDR_EL0),
   175  	}, nil
   176  }
   177  
   178  // PtraceGetRegs implements Context.PtraceGetRegs.
   179  func (s *State) PtraceGetRegs(dst io.Writer) (int, error) {
   180  	regs := s.ptraceGetRegs()
   181  	n, err := regs.WriteTo(dst)
   182  	return int(n), err
   183  }
   184  
   185  func (s *State) ptraceGetRegs() Registers {
   186  	return s.Regs
   187  }
   188  
   189  var ptraceRegistersSize = (*linux.PtraceRegs)(nil).SizeBytes()
   190  
   191  // PtraceSetRegs implements Context.PtraceSetRegs.
   192  func (s *State) PtraceSetRegs(src io.Reader) (int, error) {
   193  	var regs Registers
   194  	buf := make([]byte, ptraceRegistersSize)
   195  	if _, err := io.ReadFull(src, buf); err != nil {
   196  		return 0, err
   197  	}
   198  	regs.UnmarshalUnsafe(buf)
   199  	if !regs.validRegs() {
   200  		return 0, linuxerr.EINVAL
   201  	}
   202  	s.Regs = regs
   203  	return ptraceRegistersSize, nil
   204  }
   205  
   206  // PtraceGetFPRegs implements Context.PtraceGetFPRegs.
   207  func (s *State) PtraceGetFPRegs(dst io.Writer) (int, error) {
   208  	// TODO(gvisor.dev/issue/1238): floating-point is not supported.
   209  	return 0, nil
   210  }
   211  
   212  // PtraceSetFPRegs implements Context.PtraceSetFPRegs.
   213  func (s *State) PtraceSetFPRegs(src io.Reader) (int, error) {
   214  	// TODO(gvisor.dev/issue/1238): floating-point is not supported.
   215  	return 0, nil
   216  }
   217  
   218  // Register sets defined in include/uapi/linux/elf.h.
   219  const (
   220  	_NT_PRSTATUS = 1
   221  	_NT_PRFPREG  = 2
   222  	_NT_ARM_TLS  = 0x401
   223  )
   224  
   225  // PtraceGetRegSet implements Context.PtraceGetRegSet.
   226  func (s *State) PtraceGetRegSet(regset uintptr, dst io.Writer, maxlen int, _ cpuid.FeatureSet) (int, error) {
   227  	switch regset {
   228  	case _NT_PRSTATUS:
   229  		if maxlen < ptraceRegistersSize {
   230  			return 0, linuxerr.EFAULT
   231  		}
   232  		return s.PtraceGetRegs(dst)
   233  	default:
   234  		return 0, linuxerr.EINVAL
   235  	}
   236  }
   237  
   238  // PtraceSetRegSet implements Context.PtraceSetRegSet.
   239  func (s *State) PtraceSetRegSet(regset uintptr, src io.Reader, maxlen int, _ cpuid.FeatureSet) (int, error) {
   240  	switch regset {
   241  	case _NT_PRSTATUS:
   242  		if maxlen < ptraceRegistersSize {
   243  			return 0, linuxerr.EFAULT
   244  		}
   245  		return s.PtraceSetRegs(src)
   246  	default:
   247  		return 0, linuxerr.EINVAL
   248  	}
   249  }
   250  
   251  // FullRestore indicates whether a full restore is required.
   252  func (s *State) FullRestore() bool {
   253  	return false
   254  }
   255  
   256  // New returns a new architecture context.
   257  func New(arch Arch) *Context64 {
   258  	switch arch {
   259  	case ARM64:
   260  		return &Context64{
   261  			State{
   262  				fpState: fpu.NewState(),
   263  			},
   264  			[]fpu.State(nil),
   265  		}
   266  	}
   267  	panic(fmt.Sprintf("unknown architecture %v", arch))
   268  }