github.com/nicocha30/gvisor-ligolo@v0.0.0-20230726075806-989fa2c0a413/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/nicocha30/gvisor-ligolo/pkg/abi/linux" 25 "github.com/nicocha30/gvisor-ligolo/pkg/cpuid" 26 "github.com/nicocha30/gvisor-ligolo/pkg/errors/linuxerr" 27 "github.com/nicocha30/gvisor-ligolo/pkg/sentry/arch/fpu" 28 rpb "github.com/nicocha30/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 }