| 1 | //===-- NativeRegisterContext.cpp -----------------------------------------===// |
| 2 | // |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| 4 | // See https://llvm.org/LICENSE.txt for license information. |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| 6 | // |
| 7 | //===----------------------------------------------------------------------===// |
| 8 | |
| 9 | #include "lldb/Host/common/NativeRegisterContext.h" |
| 10 | #include "lldb/Utility/LLDBLog.h" |
| 11 | #include "lldb/Utility/RegisterValue.h" |
| 12 | |
| 13 | #include "lldb/Host/PosixApi.h" |
| 14 | #include "lldb/Host/common/NativeProcessProtocol.h" |
| 15 | #include "lldb/Host/common/NativeThreadProtocol.h" |
| 16 | |
| 17 | using namespace lldb; |
| 18 | using namespace lldb_private; |
| 19 | |
| 20 | NativeRegisterContext::NativeRegisterContext(NativeThreadProtocol &thread) |
| 21 | : m_thread(thread) {} |
| 22 | |
| 23 | // Destructor |
| 24 | NativeRegisterContext::~NativeRegisterContext() = default; |
| 25 | |
| 26 | // FIXME revisit invalidation, process stop ids, etc. Right now we don't |
| 27 | // support caching in NativeRegisterContext. We can do this later by utilizing |
| 28 | // NativeProcessProtocol::GetStopID () and adding a stop id to |
| 29 | // NativeRegisterContext. |
| 30 | |
| 31 | // void |
| 32 | // NativeRegisterContext::InvalidateIfNeeded (bool force) { |
| 33 | // ProcessSP process_sp (m_thread.GetProcess()); |
| 34 | // bool invalidate = force; |
| 35 | // uint32_t process_stop_id = UINT32_MAX; |
| 36 | |
| 37 | // if (process_sp) |
| 38 | // process_stop_id = process_sp->GetStopID(); |
| 39 | // else |
| 40 | // invalidate = true; |
| 41 | |
| 42 | // if (!invalidate) |
| 43 | // invalidate = process_stop_id != GetStopID(); |
| 44 | |
| 45 | // if (invalidate) |
| 46 | // { |
| 47 | // InvalidateAllRegisters (); |
| 48 | // SetStopID (process_stop_id); |
| 49 | // } |
| 50 | // } |
| 51 | |
| 52 | const RegisterInfo * |
| 53 | NativeRegisterContext::GetRegisterInfoByName(llvm::StringRef reg_name, |
| 54 | uint32_t start_idx) { |
| 55 | if (reg_name.empty()) |
| 56 | return nullptr; |
| 57 | |
| 58 | // Generic register names take precedence over specific register names. |
| 59 | // For example, on x86 we want "sp" to refer to the complete RSP/ESP register |
| 60 | // rather than the 16-bit SP pseudo-register. |
| 61 | uint32_t generic_reg = Args::StringToGenericRegister(s: reg_name); |
| 62 | if (generic_reg != LLDB_INVALID_REGNUM) { |
| 63 | const RegisterInfo *reg_info = |
| 64 | GetRegisterInfo(reg_kind: eRegisterKindGeneric, reg_num: generic_reg); |
| 65 | if (reg_info) |
| 66 | return reg_info; |
| 67 | } |
| 68 | |
| 69 | const uint32_t num_registers = GetRegisterCount(); |
| 70 | for (uint32_t reg = start_idx; reg < num_registers; ++reg) { |
| 71 | const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg); |
| 72 | |
| 73 | if (reg_name.equals_insensitive(RHS: reg_info->name) || |
| 74 | reg_name.equals_insensitive(RHS: reg_info->alt_name)) |
| 75 | return reg_info; |
| 76 | } |
| 77 | |
| 78 | return nullptr; |
| 79 | } |
| 80 | |
| 81 | const RegisterInfo *NativeRegisterContext::GetRegisterInfo(uint32_t kind, |
| 82 | uint32_t num) { |
| 83 | const uint32_t reg_num = ConvertRegisterKindToRegisterNumber(kind, num); |
| 84 | if (reg_num == LLDB_INVALID_REGNUM) |
| 85 | return nullptr; |
| 86 | return GetRegisterInfoAtIndex(reg: reg_num); |
| 87 | } |
| 88 | |
| 89 | const char *NativeRegisterContext::GetRegisterName(uint32_t reg) { |
| 90 | const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg); |
| 91 | if (reg_info) |
| 92 | return reg_info->name; |
| 93 | return nullptr; |
| 94 | } |
| 95 | |
| 96 | const char *NativeRegisterContext::GetRegisterSetNameForRegisterAtIndex( |
| 97 | uint32_t reg_index) const { |
| 98 | const RegisterInfo *const reg_info = GetRegisterInfoAtIndex(reg: reg_index); |
| 99 | if (!reg_info) |
| 100 | return nullptr; |
| 101 | |
| 102 | for (uint32_t set_index = 0; set_index < GetRegisterSetCount(); ++set_index) { |
| 103 | const RegisterSet *const reg_set = GetRegisterSet(set_index); |
| 104 | if (!reg_set) |
| 105 | continue; |
| 106 | |
| 107 | for (uint32_t reg_num_index = 0; reg_num_index < reg_set->num_registers; |
| 108 | ++reg_num_index) { |
| 109 | const uint32_t reg_num = reg_set->registers[reg_num_index]; |
| 110 | // FIXME double check we're checking the right register kind here. |
| 111 | if (reg_info->kinds[RegisterKind::eRegisterKindLLDB] == reg_num) { |
| 112 | // The given register is a member of this register set. Return the |
| 113 | // register set name. |
| 114 | return reg_set->name; |
| 115 | } |
| 116 | } |
| 117 | } |
| 118 | |
| 119 | // Didn't find it. |
| 120 | return nullptr; |
| 121 | } |
| 122 | |
| 123 | lldb::addr_t NativeRegisterContext::GetPC(lldb::addr_t fail_value) { |
| 124 | Log *log = GetLog(mask: LLDBLog::Thread); |
| 125 | |
| 126 | uint32_t reg = ConvertRegisterKindToRegisterNumber(kind: eRegisterKindGeneric, |
| 127 | LLDB_REGNUM_GENERIC_PC); |
| 128 | LLDB_LOGF(log, "Using reg index %" PRIu32 " (default %" PRIu64 ")" , reg, |
| 129 | fail_value); |
| 130 | |
| 131 | const uint64_t retval = ReadRegisterAsUnsigned(reg, fail_value); |
| 132 | |
| 133 | LLDB_LOGF(log, PRIu32 " retval %" PRIu64, retval); |
| 134 | |
| 135 | return retval; |
| 136 | } |
| 137 | |
| 138 | lldb::addr_t |
| 139 | NativeRegisterContext::GetPCfromBreakpointLocation(lldb::addr_t fail_value) { |
| 140 | return GetPC(fail_value); |
| 141 | } |
| 142 | |
| 143 | Status NativeRegisterContext::SetPC(lldb::addr_t pc) { |
| 144 | uint32_t reg = ConvertRegisterKindToRegisterNumber(kind: eRegisterKindGeneric, |
| 145 | LLDB_REGNUM_GENERIC_PC); |
| 146 | return WriteRegisterFromUnsigned(reg, uval: pc); |
| 147 | } |
| 148 | |
| 149 | lldb::addr_t NativeRegisterContext::GetSP(lldb::addr_t fail_value) { |
| 150 | uint32_t reg = ConvertRegisterKindToRegisterNumber(kind: eRegisterKindGeneric, |
| 151 | LLDB_REGNUM_GENERIC_SP); |
| 152 | return ReadRegisterAsUnsigned(reg, fail_value); |
| 153 | } |
| 154 | |
| 155 | Status NativeRegisterContext::SetSP(lldb::addr_t sp) { |
| 156 | uint32_t reg = ConvertRegisterKindToRegisterNumber(kind: eRegisterKindGeneric, |
| 157 | LLDB_REGNUM_GENERIC_SP); |
| 158 | return WriteRegisterFromUnsigned(reg, uval: sp); |
| 159 | } |
| 160 | |
| 161 | lldb::addr_t NativeRegisterContext::GetFP(lldb::addr_t fail_value) { |
| 162 | uint32_t reg = ConvertRegisterKindToRegisterNumber(kind: eRegisterKindGeneric, |
| 163 | LLDB_REGNUM_GENERIC_FP); |
| 164 | return ReadRegisterAsUnsigned(reg, fail_value); |
| 165 | } |
| 166 | |
| 167 | Status NativeRegisterContext::SetFP(lldb::addr_t fp) { |
| 168 | uint32_t reg = ConvertRegisterKindToRegisterNumber(kind: eRegisterKindGeneric, |
| 169 | LLDB_REGNUM_GENERIC_FP); |
| 170 | return WriteRegisterFromUnsigned(reg, uval: fp); |
| 171 | } |
| 172 | |
| 173 | lldb::addr_t NativeRegisterContext::GetReturnAddress(lldb::addr_t fail_value) { |
| 174 | uint32_t reg = ConvertRegisterKindToRegisterNumber(kind: eRegisterKindGeneric, |
| 175 | LLDB_REGNUM_GENERIC_RA); |
| 176 | return ReadRegisterAsUnsigned(reg, fail_value); |
| 177 | } |
| 178 | |
| 179 | lldb::addr_t NativeRegisterContext::GetFlags(lldb::addr_t fail_value) { |
| 180 | uint32_t reg = ConvertRegisterKindToRegisterNumber(kind: eRegisterKindGeneric, |
| 181 | LLDB_REGNUM_GENERIC_FLAGS); |
| 182 | return ReadRegisterAsUnsigned(reg, fail_value); |
| 183 | } |
| 184 | |
| 185 | lldb::addr_t |
| 186 | NativeRegisterContext::ReadRegisterAsUnsigned(uint32_t reg, |
| 187 | lldb::addr_t fail_value) { |
| 188 | if (reg != LLDB_INVALID_REGNUM) |
| 189 | return ReadRegisterAsUnsigned(reg_info: GetRegisterInfoAtIndex(reg), fail_value); |
| 190 | return fail_value; |
| 191 | } |
| 192 | |
| 193 | uint64_t |
| 194 | NativeRegisterContext::ReadRegisterAsUnsigned(const RegisterInfo *reg_info, |
| 195 | lldb::addr_t fail_value) { |
| 196 | Log *log = GetLog(mask: LLDBLog::Thread); |
| 197 | |
| 198 | if (reg_info) { |
| 199 | RegisterValue value; |
| 200 | Status error = ReadRegister(reg_info, reg_value&: value); |
| 201 | if (error.Success()) { |
| 202 | LLDB_LOGF(log, |
| 203 | "Read register succeeded: value " |
| 204 | "%" PRIu64, |
| 205 | value.GetAsUInt64()); |
| 206 | return value.GetAsUInt64(); |
| 207 | } else { |
| 208 | LLDB_LOGF(log, "Read register failed: error %s" , error.AsCString()); |
| 209 | } |
| 210 | } else { |
| 211 | LLDB_LOGF(log, "Read register failed: null reg_info" ); |
| 212 | } |
| 213 | return fail_value; |
| 214 | } |
| 215 | |
| 216 | Status NativeRegisterContext::WriteRegisterFromUnsigned(uint32_t reg, |
| 217 | uint64_t uval) { |
| 218 | if (reg == LLDB_INVALID_REGNUM) |
| 219 | return Status::FromErrorString(str: "Write register failed: reg is invalid" ); |
| 220 | return WriteRegisterFromUnsigned(reg_info: GetRegisterInfoAtIndex(reg), uval); |
| 221 | } |
| 222 | |
| 223 | Status |
| 224 | NativeRegisterContext::WriteRegisterFromUnsigned(const RegisterInfo *reg_info, |
| 225 | uint64_t uval) { |
| 226 | assert(reg_info); |
| 227 | if (!reg_info) |
| 228 | return Status::FromErrorString(str: "reg_info is nullptr" ); |
| 229 | |
| 230 | RegisterValue value; |
| 231 | if (!value.SetUInt(uint: uval, byte_size: reg_info->byte_size)) |
| 232 | return Status::FromErrorString(str: "RegisterValue::SetUInt () failed" ); |
| 233 | |
| 234 | return WriteRegister(reg_info, reg_value: value); |
| 235 | } |
| 236 | |
| 237 | lldb::tid_t NativeRegisterContext::GetThreadID() const { |
| 238 | return m_thread.GetID(); |
| 239 | } |
| 240 | |
| 241 | uint32_t NativeRegisterContext::NumSupportedHardwareBreakpoints() { return 0; } |
| 242 | |
| 243 | uint32_t NativeRegisterContext::SetHardwareBreakpoint(lldb::addr_t addr, |
| 244 | size_t size) { |
| 245 | return LLDB_INVALID_INDEX32; |
| 246 | } |
| 247 | |
| 248 | Status NativeRegisterContext::ClearAllHardwareBreakpoints() { |
| 249 | return Status::FromErrorString(str: "not implemented" ); |
| 250 | } |
| 251 | |
| 252 | bool NativeRegisterContext::ClearHardwareBreakpoint(uint32_t hw_idx) { |
| 253 | return false; |
| 254 | } |
| 255 | |
| 256 | Status NativeRegisterContext::GetHardwareBreakHitIndex(uint32_t &bp_index, |
| 257 | lldb::addr_t trap_addr) { |
| 258 | bp_index = LLDB_INVALID_INDEX32; |
| 259 | return Status::FromErrorString(str: "not implemented" ); |
| 260 | } |
| 261 | |
| 262 | uint32_t NativeRegisterContext::NumSupportedHardwareWatchpoints() { return 0; } |
| 263 | |
| 264 | uint32_t NativeRegisterContext::SetHardwareWatchpoint(lldb::addr_t addr, |
| 265 | size_t size, |
| 266 | uint32_t watch_flags) { |
| 267 | return LLDB_INVALID_INDEX32; |
| 268 | } |
| 269 | |
| 270 | bool NativeRegisterContext::ClearHardwareWatchpoint(uint32_t hw_index) { |
| 271 | return false; |
| 272 | } |
| 273 | |
| 274 | Status NativeRegisterContext::ClearWatchpointHit(uint32_t hw_index) { |
| 275 | return Status::FromErrorString(str: "not implemented" ); |
| 276 | } |
| 277 | |
| 278 | Status NativeRegisterContext::ClearAllHardwareWatchpoints() { |
| 279 | return Status::FromErrorString(str: "not implemented" ); |
| 280 | } |
| 281 | |
| 282 | Status NativeRegisterContext::IsWatchpointHit(uint32_t wp_index, bool &is_hit) { |
| 283 | is_hit = false; |
| 284 | return Status::FromErrorString(str: "not implemented" ); |
| 285 | } |
| 286 | |
| 287 | Status NativeRegisterContext::GetWatchpointHitIndex(uint32_t &wp_index, |
| 288 | lldb::addr_t trap_addr) { |
| 289 | wp_index = LLDB_INVALID_INDEX32; |
| 290 | return Status::FromErrorString(str: "not implemented" ); |
| 291 | } |
| 292 | |
| 293 | Status NativeRegisterContext::IsWatchpointVacant(uint32_t wp_index, |
| 294 | bool &is_vacant) { |
| 295 | is_vacant = false; |
| 296 | return Status::FromErrorString(str: "not implemented" ); |
| 297 | } |
| 298 | |
| 299 | lldb::addr_t NativeRegisterContext::GetWatchpointAddress(uint32_t wp_index) { |
| 300 | return LLDB_INVALID_ADDRESS; |
| 301 | } |
| 302 | |
| 303 | lldb::addr_t NativeRegisterContext::GetWatchpointHitAddress(uint32_t wp_index) { |
| 304 | return LLDB_INVALID_ADDRESS; |
| 305 | } |
| 306 | |
| 307 | bool NativeRegisterContext::HardwareSingleStep(bool enable) { return false; } |
| 308 | |
| 309 | Status NativeRegisterContext::ReadRegisterValueFromMemory( |
| 310 | const RegisterInfo *reg_info, lldb::addr_t src_addr, size_t src_len, |
| 311 | RegisterValue ®_value) { |
| 312 | Status error; |
| 313 | if (reg_info == nullptr) { |
| 314 | error = Status::FromErrorString(str: "invalid register info argument." ); |
| 315 | return error; |
| 316 | } |
| 317 | |
| 318 | // Moving from addr into a register |
| 319 | // |
| 320 | // Case 1: src_len == dst_len |
| 321 | // |
| 322 | // |AABBCCDD| Address contents |
| 323 | // |AABBCCDD| Register contents |
| 324 | // |
| 325 | // Case 2: src_len > dst_len |
| 326 | // |
| 327 | // Status! (The register should always be big enough to hold the data) |
| 328 | // |
| 329 | // Case 3: src_len < dst_len |
| 330 | // |
| 331 | // |AABB| Address contents |
| 332 | // |AABB0000| Register contents [on little-endian hardware] |
| 333 | // |0000AABB| Register contents [on big-endian hardware] |
| 334 | const size_t dst_len = reg_info->byte_size; |
| 335 | |
| 336 | if (src_len > dst_len) { |
| 337 | error = Status::FromErrorStringWithFormat( |
| 338 | format: "%" PRIu64 " bytes is too big to store in register %s (%" PRIu64 |
| 339 | " bytes)" , |
| 340 | static_cast<uint64_t>(src_len), reg_info->name, |
| 341 | static_cast<uint64_t>(dst_len)); |
| 342 | return error; |
| 343 | } |
| 344 | |
| 345 | NativeProcessProtocol &process = m_thread.GetProcess(); |
| 346 | RegisterValue::BytesContainer src(src_len); |
| 347 | |
| 348 | // Read the memory |
| 349 | size_t bytes_read; |
| 350 | error = process.ReadMemory(addr: src_addr, buf: src.data(), size: src_len, bytes_read); |
| 351 | if (error.Fail()) |
| 352 | return error; |
| 353 | |
| 354 | // Make sure the memory read succeeded... |
| 355 | if (bytes_read != src_len) { |
| 356 | // This might happen if we read _some_ bytes but not all |
| 357 | error = Status::FromErrorStringWithFormat( |
| 358 | format: "read %" PRIu64 " of %" PRIu64 " bytes" , |
| 359 | static_cast<uint64_t>(bytes_read), static_cast<uint64_t>(src_len)); |
| 360 | return error; |
| 361 | } |
| 362 | |
| 363 | // We now have a memory buffer that contains the part or all of the register |
| 364 | // value. Set the register value using this memory data. |
| 365 | // TODO: we might need to add a parameter to this function in case the byte |
| 366 | // order of the memory data doesn't match the process. For now we are |
| 367 | // assuming they are the same. |
| 368 | reg_value.SetFromMemoryData(reg_info: *reg_info, src: src.data(), src_len, |
| 369 | src_byte_order: process.GetByteOrder(), error); |
| 370 | |
| 371 | return error; |
| 372 | } |
| 373 | |
| 374 | Status NativeRegisterContext::WriteRegisterValueToMemory( |
| 375 | const RegisterInfo *reg_info, lldb::addr_t dst_addr, size_t dst_len, |
| 376 | const RegisterValue ®_value) { |
| 377 | Status error; |
| 378 | if (reg_info == nullptr) { |
| 379 | error = Status::FromErrorString(str: "Invalid register info argument." ); |
| 380 | return error; |
| 381 | } |
| 382 | |
| 383 | RegisterValue::BytesContainer dst(dst_len); |
| 384 | NativeProcessProtocol &process = m_thread.GetProcess(); |
| 385 | |
| 386 | // TODO: we might need to add a parameter to this function in case the byte |
| 387 | // order of the memory data doesn't match the process. For now we are |
| 388 | // assuming they are the same. |
| 389 | const size_t bytes_copied = reg_value.GetAsMemoryData( |
| 390 | reg_info: *reg_info, dst: dst.data(), dst_len, dst_byte_order: process.GetByteOrder(), error); |
| 391 | |
| 392 | if (error.Success()) { |
| 393 | if (bytes_copied == 0) { |
| 394 | error = Status::FromErrorString(str: "byte copy failed." ); |
| 395 | } else { |
| 396 | size_t bytes_written; |
| 397 | error = process.WriteMemory(addr: dst_addr, buf: dst.data(), size: bytes_copied, |
| 398 | bytes_written); |
| 399 | if (error.Fail()) |
| 400 | return error; |
| 401 | |
| 402 | if (bytes_written != bytes_copied) { |
| 403 | // This might happen if we read _some_ bytes but not all |
| 404 | error = Status::FromErrorStringWithFormat( |
| 405 | format: "only wrote %" PRIu64 " of %" PRIu64 " bytes" , |
| 406 | static_cast<uint64_t>(bytes_written), |
| 407 | static_cast<uint64_t>(bytes_copied)); |
| 408 | } |
| 409 | } |
| 410 | } |
| 411 | |
| 412 | return error; |
| 413 | } |
| 414 | |
| 415 | uint32_t |
| 416 | NativeRegisterContext::ConvertRegisterKindToRegisterNumber(uint32_t kind, |
| 417 | uint32_t num) const { |
| 418 | const uint32_t num_regs = GetRegisterCount(); |
| 419 | |
| 420 | assert(kind < kNumRegisterKinds); |
| 421 | for (uint32_t reg_idx = 0; reg_idx < num_regs; ++reg_idx) { |
| 422 | const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg: reg_idx); |
| 423 | |
| 424 | if (reg_info->kinds[kind] == num) |
| 425 | return reg_idx; |
| 426 | } |
| 427 | |
| 428 | return LLDB_INVALID_REGNUM; |
| 429 | } |
| 430 | |
| 431 | std::vector<uint32_t> |
| 432 | NativeRegisterContext::GetExpeditedRegisters(ExpeditedRegs expType) const { |
| 433 | if (expType == ExpeditedRegs::Minimal) { |
| 434 | // Expedite only a minimum set of important generic registers. |
| 435 | static const uint32_t k_expedited_registers[] = { |
| 436 | LLDB_REGNUM_GENERIC_PC, LLDB_REGNUM_GENERIC_SP, LLDB_REGNUM_GENERIC_FP, |
| 437 | LLDB_REGNUM_GENERIC_RA}; |
| 438 | |
| 439 | std::vector<uint32_t> expedited_reg_nums; |
| 440 | for (uint32_t gen_reg : k_expedited_registers) { |
| 441 | uint32_t reg_num = |
| 442 | ConvertRegisterKindToRegisterNumber(kind: eRegisterKindGeneric, num: gen_reg); |
| 443 | if (reg_num == LLDB_INVALID_REGNUM) |
| 444 | continue; // Target does not support the given register. |
| 445 | else |
| 446 | expedited_reg_nums.push_back(x: reg_num); |
| 447 | } |
| 448 | |
| 449 | return expedited_reg_nums; |
| 450 | } |
| 451 | |
| 452 | if (GetRegisterSetCount() > 0 && expType == ExpeditedRegs::Full) |
| 453 | return std::vector<uint32_t>(GetRegisterSet(set_index: 0)->registers, |
| 454 | GetRegisterSet(set_index: 0)->registers + |
| 455 | GetRegisterSet(set_index: 0)->num_registers); |
| 456 | |
| 457 | return std::vector<uint32_t>(); |
| 458 | } |
| 459 | |