| //===-- RegisterContextMemory.cpp -----------------------------------------===// | |
| // | |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| // See https://llvm.org/LICENSE.txt for license information. | |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| // | |
| //===----------------------------------------------------------------------===// | |
| #include "RegisterContextMemory.h" | |
| #include "lldb/Target/Process.h" | |
| #include "lldb/Target/Thread.h" | |
| #include "lldb/Utility/DataBufferHeap.h" | |
| #include "lldb/Utility/RegisterValue.h" | |
| #include "lldb/Utility/Status.h" | |
| using namespace lldb; | |
| using namespace lldb_private; | |
| // RegisterContextMemory constructor | |
| RegisterContextMemory::RegisterContextMemory(Thread &thread, | |
| uint32_t concrete_frame_idx, | |
| DynamicRegisterInfoSP reg_infos_sp, | |
| addr_t reg_data_addr) | |
| : RegisterContext(thread, concrete_frame_idx), | |
| m_reg_infos_sp(std::move(reg_infos_sp)), m_reg_valid(), m_reg_data(), | |
| m_reg_data_addr(reg_data_addr) { | |
| // Resize our vector of bools to contain one bool for every register. We will | |
| // use these boolean values to know when a register value is valid in | |
| // m_reg_data. | |
| const size_t num_regs = m_reg_infos_sp->GetNumRegisters(); | |
| assert(num_regs > 0); | |
| m_reg_valid.resize(num_regs); | |
| // Make a heap based buffer that is big enough to store all registers | |
| m_data = std::make_shared<DataBufferHeap>( | |
| m_reg_infos_sp->GetRegisterDataByteSize(), 0); | |
| m_reg_data.SetData(m_data); | |
| } | |
| // Destructor | |
| RegisterContextMemory::~RegisterContextMemory() = default; | |
| void RegisterContextMemory::InvalidateAllRegisters() { | |
| if (m_reg_data_addr != LLDB_INVALID_ADDRESS) | |
| SetAllRegisterValid(false); | |
| } | |
| void RegisterContextMemory::SetAllRegisterValid(bool b) { | |
| std::vector<bool>::iterator pos, end = m_reg_valid.end(); | |
| for (pos = m_reg_valid.begin(); pos != end; ++pos) | |
| *pos = b; | |
| } | |
| size_t RegisterContextMemory::GetRegisterCount() { | |
| return m_reg_infos_sp->GetNumRegisters(); | |
| } | |
| const RegisterInfo *RegisterContextMemory::GetRegisterInfoAtIndex(size_t reg) { | |
| return m_reg_infos_sp->GetRegisterInfoAtIndex(reg); | |
| } | |
| size_t RegisterContextMemory::GetRegisterSetCount() { | |
| return m_reg_infos_sp->GetNumRegisterSets(); | |
| } | |
| const RegisterSet *RegisterContextMemory::GetRegisterSet(size_t reg_set) { | |
| return m_reg_infos_sp->GetRegisterSet(reg_set); | |
| } | |
| uint32_t RegisterContextMemory::ConvertRegisterKindToRegisterNumber( | |
| lldb::RegisterKind kind, uint32_t num) { | |
| return m_reg_infos_sp->ConvertRegisterKindToRegisterNumber(kind, num); | |
| } | |
| bool RegisterContextMemory::ReadRegister(const RegisterInfo *reg_info, | |
| RegisterValue ®_value) { | |
| const uint32_t reg_num = reg_info->kinds[eRegisterKindLLDB]; | |
| if (!m_reg_valid[reg_num]) { | |
| if (!ReadAllRegisterValues(m_data)) | |
| return false; | |
| } | |
| const bool partial_data_ok = false; | |
| return reg_value | |
| .SetValueFromData(*reg_info, m_reg_data, reg_info->byte_offset, | |
| partial_data_ok) | |
| .Success(); | |
| } | |
| bool RegisterContextMemory::WriteRegister(const RegisterInfo *reg_info, | |
| const RegisterValue ®_value) { | |
| if (m_reg_data_addr != LLDB_INVALID_ADDRESS) { | |
| const uint32_t reg_num = reg_info->kinds[eRegisterKindLLDB]; | |
| addr_t reg_addr = m_reg_data_addr + reg_info->byte_offset; | |
| Status error(WriteRegisterValueToMemory(reg_info, reg_addr, | |
| reg_info->byte_size, reg_value)); | |
| m_reg_valid[reg_num] = false; | |
| return error.Success(); | |
| } | |
| return false; | |
| } | |
| bool RegisterContextMemory::ReadAllRegisterValues( | |
| WritableDataBufferSP &data_sp) { | |
| if (m_reg_data_addr != LLDB_INVALID_ADDRESS) { | |
| ProcessSP process_sp(CalculateProcess()); | |
| if (process_sp) { | |
| Status error; | |
| if (process_sp->ReadMemory(m_reg_data_addr, data_sp->GetBytes(), | |
| data_sp->GetByteSize(), | |
| error) == data_sp->GetByteSize()) { | |
| SetAllRegisterValid(true); | |
| return true; | |
| } | |
| } | |
| } | |
| return false; | |
| } | |
| bool RegisterContextMemory::WriteAllRegisterValues( | |
| const DataBufferSP &data_sp) { | |
| if (m_reg_data_addr != LLDB_INVALID_ADDRESS) { | |
| ProcessSP process_sp(CalculateProcess()); | |
| if (process_sp) { | |
| Status error; | |
| SetAllRegisterValid(false); | |
| if (process_sp->WriteMemory(m_reg_data_addr, data_sp->GetBytes(), | |
| data_sp->GetByteSize(), | |
| error) == data_sp->GetByteSize()) | |
| return true; | |
| } | |
| } | |
| return false; | |
| } | |
| void RegisterContextMemory::SetAllRegisterData( | |
| const lldb::DataBufferSP &data_sp) { | |
| m_reg_data.SetData(data_sp); | |
| SetAllRegisterValid(true); | |
| } |