brintos

brintos / llvm-project-archived public Read only

0
0
Text · 15.4 KiB · 8a1cfbc Raw
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 &reg_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 &reg_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