1 //===-- NativeRegisterContextLinux.cpp --------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "NativeRegisterContextLinux.h" 11 12 #include "lldb/Core/RegisterValue.h" 13 #include "lldb/Host/common/NativeProcessProtocol.h" 14 #include "lldb/Host/common/NativeThreadProtocol.h" 15 #include "lldb/Host/linux/Ptrace.h" 16 17 #include "Plugins/Process/POSIX/ProcessPOSIXLog.h" 18 19 using namespace lldb_private; 20 using namespace lldb_private::process_linux; 21 22 namespace 23 { 24 25 class ReadRegOperation : public NativeProcessLinux::Operation 26 { 27 public: 28 ReadRegOperation(lldb::tid_t tid, uint32_t offset, const char *reg_name, RegisterValue &value) : 29 m_tid(tid), 30 m_offset(static_cast<uintptr_t>(offset)), 31 m_reg_name(reg_name), 32 m_value(value) 33 { } 34 35 void 36 Execute(NativeProcessLinux *monitor) override; 37 38 private: 39 lldb::tid_t m_tid; 40 uintptr_t m_offset; 41 const char *m_reg_name; 42 RegisterValue &m_value; 43 }; 44 45 class WriteRegOperation : public NativeProcessLinux::Operation 46 { 47 public: 48 WriteRegOperation(lldb::tid_t tid, unsigned offset, const char *reg_name, const RegisterValue &value) : 49 m_tid(tid), 50 m_offset(offset), 51 m_reg_name(reg_name), 52 m_value(value) 53 { } 54 55 void 56 Execute(NativeProcessLinux *monitor) override; 57 58 private: 59 lldb::tid_t m_tid; 60 uintptr_t m_offset; 61 const char *m_reg_name; 62 const RegisterValue &m_value; 63 }; 64 65 class ReadGPROperation : public NativeProcessLinux::Operation 66 { 67 public: 68 ReadGPROperation(lldb::tid_t tid, void *buf, size_t buf_size) : 69 m_tid(tid), m_buf(buf), m_buf_size(buf_size) 70 { } 71 72 void Execute(NativeProcessLinux *monitor) override; 73 74 private: 75 lldb::tid_t m_tid; 76 void *m_buf; 77 size_t m_buf_size; 78 }; 79 80 class WriteGPROperation : public NativeProcessLinux::Operation 81 { 82 public: 83 WriteGPROperation(lldb::tid_t tid, void *buf, size_t buf_size) : 84 m_tid(tid), m_buf(buf), m_buf_size(buf_size) 85 { } 86 87 void Execute(NativeProcessLinux *monitor) override; 88 89 private: 90 lldb::tid_t m_tid; 91 void *m_buf; 92 size_t m_buf_size; 93 }; 94 95 class ReadFPROperation : public NativeProcessLinux::Operation 96 { 97 public: 98 ReadFPROperation(lldb::tid_t tid, void *buf, size_t buf_size) : 99 m_tid(tid), m_buf(buf), m_buf_size(buf_size) 100 { } 101 102 void Execute(NativeProcessLinux *monitor) override; 103 104 private: 105 lldb::tid_t m_tid; 106 void *m_buf; 107 size_t m_buf_size; 108 }; 109 110 class WriteFPROperation : public NativeProcessLinux::Operation 111 { 112 public: 113 WriteFPROperation(lldb::tid_t tid, void *buf, size_t buf_size) : 114 m_tid(tid), m_buf(buf), m_buf_size(buf_size) 115 { } 116 117 void Execute(NativeProcessLinux *monitor) override; 118 119 private: 120 lldb::tid_t m_tid; 121 void *m_buf; 122 size_t m_buf_size; 123 }; 124 125 class ReadRegisterSetOperation : public NativeProcessLinux::Operation 126 { 127 public: 128 ReadRegisterSetOperation(lldb::tid_t tid, void *buf, size_t buf_size, unsigned int regset) : 129 m_tid(tid), m_buf(buf), m_buf_size(buf_size), m_regset(regset) 130 { } 131 132 void Execute(NativeProcessLinux *monitor) override; 133 134 private: 135 lldb::tid_t m_tid; 136 void *m_buf; 137 size_t m_buf_size; 138 const unsigned int m_regset; 139 }; 140 141 class WriteRegisterSetOperation : public NativeProcessLinux::Operation 142 { 143 public: 144 WriteRegisterSetOperation(lldb::tid_t tid, void *buf, size_t buf_size, unsigned int regset) : 145 m_tid(tid), m_buf(buf), m_buf_size(buf_size), m_regset(regset) 146 { } 147 148 void Execute(NativeProcessLinux *monitor) override; 149 150 private: 151 lldb::tid_t m_tid; 152 void *m_buf; 153 size_t m_buf_size; 154 const unsigned int m_regset; 155 }; 156 157 } // end of anonymous namespace 158 159 void 160 ReadRegOperation::Execute(NativeProcessLinux *monitor) 161 { 162 Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_REGISTERS)); 163 164 lldb::addr_t data = static_cast<unsigned long>(NativeProcessLinux::PtraceWrapper(PTRACE_PEEKUSER, m_tid, (void*)m_offset, nullptr, 0, m_error)); 165 if (m_error.Success()) 166 m_value = data; 167 168 if (log) 169 log->Printf ("NativeProcessLinux::%s() reg %s: 0x%" PRIx64, __FUNCTION__, m_reg_name, data); 170 } 171 172 void 173 WriteRegOperation::Execute(NativeProcessLinux *monitor) 174 { 175 Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_REGISTERS)); 176 177 void* buf = (void*)m_value.GetAsUInt64(); 178 179 if (log) 180 log->Printf ("NativeProcessLinux::%s() reg %s: %p", __FUNCTION__, m_reg_name, buf); 181 NativeProcessLinux::PtraceWrapper(PTRACE_POKEUSER, m_tid, (void*)m_offset, buf, 0, m_error); 182 } 183 184 void 185 ReadGPROperation::Execute(NativeProcessLinux *monitor) 186 { 187 NativeProcessLinux::PtraceWrapper(PTRACE_GETREGS, m_tid, nullptr, m_buf, m_buf_size, m_error); 188 } 189 190 void 191 WriteGPROperation::Execute(NativeProcessLinux *monitor) 192 { 193 NativeProcessLinux::PtraceWrapper(PTRACE_SETREGS, m_tid, nullptr, m_buf, m_buf_size, m_error); 194 } 195 196 void 197 ReadFPROperation::Execute(NativeProcessLinux *monitor) 198 { 199 NativeProcessLinux::PtraceWrapper(PTRACE_GETFPREGS, m_tid, nullptr, m_buf, m_buf_size, m_error); 200 } 201 202 void 203 WriteFPROperation::Execute(NativeProcessLinux *monitor) 204 { 205 NativeProcessLinux::PtraceWrapper(PTRACE_SETFPREGS, m_tid, nullptr, m_buf, m_buf_size, m_error); 206 } 207 208 void 209 ReadRegisterSetOperation::Execute(NativeProcessLinux *monitor) 210 { 211 NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, m_tid, (void *)&m_regset, m_buf, m_buf_size, m_error); 212 } 213 214 void 215 WriteRegisterSetOperation::Execute(NativeProcessLinux *monitor) 216 { 217 NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, m_tid, (void *)&m_regset, m_buf, m_buf_size, m_error); 218 } 219 220 NativeRegisterContextLinux::NativeRegisterContextLinux(NativeThreadProtocol &native_thread, 221 uint32_t concrete_frame_idx, 222 RegisterInfoInterface *reg_info_interface_p) : 223 NativeRegisterContextRegisterInfo(native_thread, concrete_frame_idx, reg_info_interface_p) 224 {} 225 226 lldb::ByteOrder 227 NativeRegisterContextLinux::GetByteOrder() const 228 { 229 // Get the target process whose privileged thread was used for the register read. 230 lldb::ByteOrder byte_order = lldb::eByteOrderInvalid; 231 232 NativeProcessProtocolSP process_sp (m_thread.GetProcess ()); 233 if (!process_sp) 234 return byte_order; 235 236 if (!process_sp->GetByteOrder (byte_order)) 237 { 238 // FIXME log here 239 } 240 241 return byte_order; 242 } 243 244 Error 245 NativeRegisterContextLinux::ReadRegisterRaw(uint32_t reg_index, RegisterValue ®_value) 246 { 247 const RegisterInfo *const reg_info = GetRegisterInfoAtIndex(reg_index); 248 if (!reg_info) 249 return Error("register %" PRIu32 " not found", reg_index); 250 251 NativeProcessProtocolSP process_sp(m_thread.GetProcess()); 252 if (!process_sp) 253 return Error("NativeProcessProtocol is NULL"); 254 255 NativeProcessLinux* process_p = static_cast<NativeProcessLinux*>(process_sp.get()); 256 return process_p->DoOperation(GetReadRegisterValueOperation(reg_info->byte_offset, 257 reg_info->name, 258 reg_info->byte_size, 259 reg_value)); 260 } 261 262 Error 263 NativeRegisterContextLinux::WriteRegisterRaw(uint32_t reg_index, const RegisterValue ®_value) 264 { 265 uint32_t reg_to_write = reg_index; 266 RegisterValue value_to_write = reg_value; 267 268 // Check if this is a subregister of a full register. 269 const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg_index); 270 if (reg_info->invalidate_regs && (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM)) 271 { 272 Error error; 273 274 RegisterValue full_value; 275 uint32_t full_reg = reg_info->invalidate_regs[0]; 276 const RegisterInfo *full_reg_info = GetRegisterInfoAtIndex(full_reg); 277 278 // Read the full register. 279 error = ReadRegister(full_reg_info, full_value); 280 if (error.Fail ()) 281 return error; 282 283 lldb::ByteOrder byte_order = GetByteOrder(); 284 uint8_t dst[RegisterValue::kMaxRegisterByteSize]; 285 286 // Get the bytes for the full register. 287 const uint32_t dest_size = full_value.GetAsMemoryData (full_reg_info, 288 dst, 289 sizeof(dst), 290 byte_order, 291 error); 292 if (error.Success() && dest_size) 293 { 294 uint8_t src[RegisterValue::kMaxRegisterByteSize]; 295 296 // Get the bytes for the source data. 297 const uint32_t src_size = reg_value.GetAsMemoryData (reg_info, src, sizeof(src), byte_order, error); 298 if (error.Success() && src_size && (src_size < dest_size)) 299 { 300 // Copy the src bytes to the destination. 301 memcpy (dst + (reg_info->byte_offset & 0x1), src, src_size); 302 // Set this full register as the value to write. 303 value_to_write.SetBytes(dst, full_value.GetByteSize(), byte_order); 304 value_to_write.SetType(full_reg_info); 305 reg_to_write = full_reg; 306 } 307 } 308 } 309 310 NativeProcessProtocolSP process_sp (m_thread.GetProcess ()); 311 if (!process_sp) 312 return Error("NativeProcessProtocol is NULL"); 313 314 const RegisterInfo *const register_to_write_info_p = GetRegisterInfoAtIndex (reg_to_write); 315 assert (register_to_write_info_p && "register to write does not have valid RegisterInfo"); 316 if (!register_to_write_info_p) 317 return Error("NativeRegisterContextLinux::%s failed to get RegisterInfo for write register index %" PRIu32, __FUNCTION__, reg_to_write); 318 319 NativeProcessLinux* process_p = static_cast<NativeProcessLinux*> (process_sp.get ()); 320 return process_p->DoOperation(GetWriteRegisterValueOperation(reg_info->byte_offset, 321 reg_info->name, 322 reg_value)); 323 } 324 325 Error 326 NativeRegisterContextLinux::ReadGPR() 327 { 328 NativeProcessProtocolSP process_sp (m_thread.GetProcess ()); 329 if (!process_sp) 330 return Error("NativeProcessProtocol is NULL"); 331 332 void* buf = GetGPRBuffer(); 333 if (!buf) 334 return Error("GPR buffer is NULL"); 335 size_t buf_size = GetGPRSize(); 336 337 NativeProcessLinux* process_p = static_cast<NativeProcessLinux*>(process_sp.get()); 338 return process_p->DoOperation(GetReadGPROperation(buf, buf_size)); 339 } 340 341 Error 342 NativeRegisterContextLinux::WriteGPR() 343 { 344 NativeProcessProtocolSP process_sp (m_thread.GetProcess ()); 345 if (!process_sp) 346 return Error("NativeProcessProtocol is NULL"); 347 348 void* buf = GetGPRBuffer(); 349 if (!buf) 350 return Error("GPR buffer is NULL"); 351 size_t buf_size = GetGPRSize(); 352 353 NativeProcessLinux* process_p = static_cast<NativeProcessLinux*>(process_sp.get()); 354 return process_p->DoOperation(GetWriteGPROperation(buf, buf_size)); 355 } 356 357 Error 358 NativeRegisterContextLinux::ReadFPR() 359 { 360 NativeProcessProtocolSP process_sp (m_thread.GetProcess ()); 361 if (!process_sp) 362 return Error("NativeProcessProtocol is NULL"); 363 364 void* buf = GetFPRBuffer(); 365 if (!buf) 366 return Error("GPR buffer is NULL"); 367 size_t buf_size = GetFPRSize(); 368 369 NativeProcessLinux* process_p = static_cast<NativeProcessLinux*>(process_sp.get()); 370 return process_p->DoOperation(GetReadFPROperation(buf, buf_size)); 371 } 372 373 Error 374 NativeRegisterContextLinux::WriteFPR() 375 { 376 NativeProcessProtocolSP process_sp (m_thread.GetProcess ()); 377 if (!process_sp) 378 return Error("NativeProcessProtocol is NULL"); 379 380 void* buf = GetFPRBuffer(); 381 if (!buf) 382 return Error("GPR buffer is NULL"); 383 size_t buf_size = GetFPRSize(); 384 385 NativeProcessLinux* process_p = static_cast<NativeProcessLinux*>(process_sp.get()); 386 return process_p->DoOperation(GetWriteFPROperation(buf, buf_size)); 387 } 388 389 Error 390 NativeRegisterContextLinux::ReadRegisterSet(void *buf, size_t buf_size, unsigned int regset) 391 { 392 NativeProcessProtocolSP process_sp (m_thread.GetProcess()); 393 if (!process_sp) 394 return Error("NativeProcessProtocol is NULL"); 395 NativeProcessLinux* process_p = static_cast<NativeProcessLinux*>(process_sp.get()); 396 397 ReadRegisterSetOperation op(m_thread.GetID(), buf, buf_size, regset); 398 return process_p->DoOperation(&op); 399 } 400 401 Error 402 NativeRegisterContextLinux::WriteRegisterSet(void *buf, size_t buf_size, unsigned int regset) 403 { 404 NativeProcessProtocolSP process_sp (m_thread.GetProcess()); 405 if (!process_sp) 406 return Error("NativeProcessProtocol is NULL"); 407 NativeProcessLinux* process_p = static_cast<NativeProcessLinux*>(process_sp.get()); 408 409 WriteRegisterSetOperation op(m_thread.GetID(), buf, buf_size, regset); 410 return process_p->DoOperation(&op); 411 } 412 413 NativeProcessLinux::OperationUP 414 NativeRegisterContextLinux::GetReadRegisterValueOperation(uint32_t offset, 415 const char* reg_name, 416 uint32_t size, 417 RegisterValue &value) 418 { 419 return NativeProcessLinux::OperationUP(new ReadRegOperation(m_thread.GetID(), offset, reg_name, value)); 420 } 421 422 NativeProcessLinux::OperationUP 423 NativeRegisterContextLinux::GetWriteRegisterValueOperation(uint32_t offset, 424 const char* reg_name, 425 const RegisterValue &value) 426 { 427 return NativeProcessLinux::OperationUP(new WriteRegOperation(m_thread.GetID(), offset, reg_name, value)); 428 } 429 430 NativeProcessLinux::OperationUP 431 NativeRegisterContextLinux::GetReadGPROperation(void *buf, size_t buf_size) 432 { 433 return NativeProcessLinux::OperationUP(new ReadGPROperation(m_thread.GetID(), buf, buf_size)); 434 } 435 436 NativeProcessLinux::OperationUP 437 NativeRegisterContextLinux::GetWriteGPROperation(void *buf, size_t buf_size) 438 { 439 return NativeProcessLinux::OperationUP(new WriteGPROperation(m_thread.GetID(), buf, buf_size)); 440 } 441 442 NativeProcessLinux::OperationUP 443 NativeRegisterContextLinux::GetReadFPROperation(void *buf, size_t buf_size) 444 { 445 return NativeProcessLinux::OperationUP(new ReadFPROperation(m_thread.GetID(), buf, buf_size)); 446 } 447 448 NativeProcessLinux::OperationUP 449 NativeRegisterContextLinux::GetWriteFPROperation(void *buf, size_t buf_size) 450 { 451 return NativeProcessLinux::OperationUP(new WriteFPROperation(m_thread.GetID(), buf, buf_size)); 452 } 453