459 lines · cpp
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-exception6//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 17using namespace lldb;18using namespace lldb_private;19 20NativeRegisterContext::NativeRegisterContext(NativeThreadProtocol &thread)21 : m_thread(thread) {}22 23// Destructor24NativeRegisterContext::~NativeRegisterContext() = default;25 26// FIXME revisit invalidation, process stop ids, etc. Right now we don't27// support caching in NativeRegisterContext. We can do this later by utilizing28// NativeProcessProtocol::GetStopID () and adding a stop id to29// NativeRegisterContext.30 31// void32// 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// else40// 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 52const RegisterInfo *53NativeRegisterContext::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 register60 // rather than the 16-bit SP pseudo-register.61 uint32_t generic_reg = Args::StringToGenericRegister(reg_name);62 if (generic_reg != LLDB_INVALID_REGNUM) {63 const RegisterInfo *reg_info =64 GetRegisterInfo(eRegisterKindGeneric, 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(reg_info->name) ||74 reg_name.equals_insensitive(reg_info->alt_name))75 return reg_info;76 }77 78 return nullptr;79}80 81const 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_num);87}88 89const 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 96const char *NativeRegisterContext::GetRegisterSetNameForRegisterAtIndex(97 uint32_t reg_index) const {98 const RegisterInfo *const reg_info = GetRegisterInfoAtIndex(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 the113 // register set name.114 return reg_set->name;115 }116 }117 }118 119 // Didn't find it.120 return nullptr;121}122 123lldb::addr_t NativeRegisterContext::GetPC(lldb::addr_t fail_value) {124 Log *log = GetLog(LLDBLog::Thread);125 126 uint32_t reg = ConvertRegisterKindToRegisterNumber(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 138lldb::addr_t139NativeRegisterContext::GetPCfromBreakpointLocation(lldb::addr_t fail_value) {140 return GetPC(fail_value);141}142 143Status NativeRegisterContext::SetPC(lldb::addr_t pc) {144 uint32_t reg = ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric,145 LLDB_REGNUM_GENERIC_PC);146 return WriteRegisterFromUnsigned(reg, pc);147}148 149lldb::addr_t NativeRegisterContext::GetSP(lldb::addr_t fail_value) {150 uint32_t reg = ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric,151 LLDB_REGNUM_GENERIC_SP);152 return ReadRegisterAsUnsigned(reg, fail_value);153}154 155Status NativeRegisterContext::SetSP(lldb::addr_t sp) {156 uint32_t reg = ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric,157 LLDB_REGNUM_GENERIC_SP);158 return WriteRegisterFromUnsigned(reg, sp);159}160 161lldb::addr_t NativeRegisterContext::GetFP(lldb::addr_t fail_value) {162 uint32_t reg = ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric,163 LLDB_REGNUM_GENERIC_FP);164 return ReadRegisterAsUnsigned(reg, fail_value);165}166 167Status NativeRegisterContext::SetFP(lldb::addr_t fp) {168 uint32_t reg = ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric,169 LLDB_REGNUM_GENERIC_FP);170 return WriteRegisterFromUnsigned(reg, fp);171}172 173lldb::addr_t NativeRegisterContext::GetReturnAddress(lldb::addr_t fail_value) {174 uint32_t reg = ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric,175 LLDB_REGNUM_GENERIC_RA);176 return ReadRegisterAsUnsigned(reg, fail_value);177}178 179lldb::addr_t NativeRegisterContext::GetFlags(lldb::addr_t fail_value) {180 uint32_t reg = ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric,181 LLDB_REGNUM_GENERIC_FLAGS);182 return ReadRegisterAsUnsigned(reg, fail_value);183}184 185lldb::addr_t186NativeRegisterContext::ReadRegisterAsUnsigned(uint32_t reg,187 lldb::addr_t fail_value) {188 if (reg != LLDB_INVALID_REGNUM)189 return ReadRegisterAsUnsigned(GetRegisterInfoAtIndex(reg), fail_value);190 return fail_value;191}192 193uint64_t194NativeRegisterContext::ReadRegisterAsUnsigned(const RegisterInfo *reg_info,195 lldb::addr_t fail_value) {196 Log *log = GetLog(LLDBLog::Thread);197 198 if (reg_info) {199 RegisterValue value;200 Status error = ReadRegister(reg_info, 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 216Status NativeRegisterContext::WriteRegisterFromUnsigned(uint32_t reg,217 uint64_t uval) {218 if (reg == LLDB_INVALID_REGNUM)219 return Status::FromErrorString("Write register failed: reg is invalid");220 return WriteRegisterFromUnsigned(GetRegisterInfoAtIndex(reg), uval);221}222 223Status224NativeRegisterContext::WriteRegisterFromUnsigned(const RegisterInfo *reg_info,225 uint64_t uval) {226 assert(reg_info);227 if (!reg_info)228 return Status::FromErrorString("reg_info is nullptr");229 230 RegisterValue value;231 if (!value.SetUInt(uval, reg_info->byte_size))232 return Status::FromErrorString("RegisterValue::SetUInt () failed");233 234 return WriteRegister(reg_info, value);235}236 237lldb::tid_t NativeRegisterContext::GetThreadID() const {238 return m_thread.GetID();239}240 241uint32_t NativeRegisterContext::NumSupportedHardwareBreakpoints() { return 0; }242 243uint32_t NativeRegisterContext::SetHardwareBreakpoint(lldb::addr_t addr,244 size_t size) {245 return LLDB_INVALID_INDEX32;246}247 248Status NativeRegisterContext::ClearAllHardwareBreakpoints() {249 return Status::FromErrorString("not implemented");250}251 252bool NativeRegisterContext::ClearHardwareBreakpoint(uint32_t hw_idx) {253 return false;254}255 256Status NativeRegisterContext::GetHardwareBreakHitIndex(uint32_t &bp_index,257 lldb::addr_t trap_addr) {258 bp_index = LLDB_INVALID_INDEX32;259 return Status::FromErrorString("not implemented");260}261 262uint32_t NativeRegisterContext::NumSupportedHardwareWatchpoints() { return 0; }263 264uint32_t NativeRegisterContext::SetHardwareWatchpoint(lldb::addr_t addr,265 size_t size,266 uint32_t watch_flags) {267 return LLDB_INVALID_INDEX32;268}269 270bool NativeRegisterContext::ClearHardwareWatchpoint(uint32_t hw_index) {271 return false;272}273 274Status NativeRegisterContext::ClearWatchpointHit(uint32_t hw_index) {275 return Status::FromErrorString("not implemented");276}277 278Status NativeRegisterContext::ClearAllHardwareWatchpoints() {279 return Status::FromErrorString("not implemented");280}281 282Status NativeRegisterContext::IsWatchpointHit(uint32_t wp_index, bool &is_hit) {283 is_hit = false;284 return Status::FromErrorString("not implemented");285}286 287Status NativeRegisterContext::GetWatchpointHitIndex(uint32_t &wp_index,288 lldb::addr_t trap_addr) {289 wp_index = LLDB_INVALID_INDEX32;290 return Status::FromErrorString("not implemented");291}292 293Status NativeRegisterContext::IsWatchpointVacant(uint32_t wp_index,294 bool &is_vacant) {295 is_vacant = false;296 return Status::FromErrorString("not implemented");297}298 299lldb::addr_t NativeRegisterContext::GetWatchpointAddress(uint32_t wp_index) {300 return LLDB_INVALID_ADDRESS;301}302 303lldb::addr_t NativeRegisterContext::GetWatchpointHitAddress(uint32_t wp_index) {304 return LLDB_INVALID_ADDRESS;305}306 307bool NativeRegisterContext::HardwareSingleStep(bool enable) { return false; }308 309Status 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("invalid register info argument.");315 return error;316 }317 318 // Moving from addr into a register319 //320 // Case 1: src_len == dst_len321 //322 // |AABBCCDD| Address contents323 // |AABBCCDD| Register contents324 //325 // Case 2: src_len > dst_len326 //327 // Status! (The register should always be big enough to hold the data)328 //329 // Case 3: src_len < dst_len330 //331 // |AABB| Address contents332 // |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 "%" PRIu64 " bytes is too big to store in register %s (%" PRIu64339 " 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 memory349 size_t bytes_read;350 error = process.ReadMemory(src_addr, src.data(), 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 all357 error = Status::FromErrorStringWithFormat(358 "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 register364 // value. Set the register value using this memory data.365 // TODO: we might need to add a parameter to this function in case the byte366 // order of the memory data doesn't match the process. For now we are367 // assuming they are the same.368 reg_value.SetFromMemoryData(*reg_info, src.data(), src_len,369 process.GetByteOrder(), error);370 371 return error;372}373 374Status 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("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 byte387 // order of the memory data doesn't match the process. For now we are388 // assuming they are the same.389 const size_t bytes_copied = reg_value.GetAsMemoryData(390 *reg_info, dst.data(), dst_len, process.GetByteOrder(), error);391 392 if (error.Success()) {393 if (bytes_copied == 0) {394 error = Status::FromErrorString("byte copy failed.");395 } else {396 size_t bytes_written;397 error = process.WriteMemory(dst_addr, dst.data(), 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 all404 error = Status::FromErrorStringWithFormat(405 "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 415uint32_t416NativeRegisterContext::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_idx);423 424 if (reg_info->kinds[kind] == num)425 return reg_idx;426 }427 428 return LLDB_INVALID_REGNUM;429}430 431std::vector<uint32_t>432NativeRegisterContext::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(eRegisterKindGeneric, gen_reg);443 if (reg_num == LLDB_INVALID_REGNUM)444 continue; // Target does not support the given register.445 else446 expedited_reg_nums.push_back(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(0)->registers,454 GetRegisterSet(0)->registers +455 GetRegisterSet(0)->num_registers);456 457 return std::vector<uint32_t>();458}459