1 //===-- RegisterContextMemory.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 "RegisterContextMemory.h" 10 11 #include "lldb/Target/Process.h" 12 #include "lldb/Target/Thread.h" 13 #include "lldb/Utility/DataBufferHeap.h" 14 #include "lldb/Utility/RegisterValue.h" 15 #include "lldb/Utility/Status.h" 16 17 using namespace lldb; 18 using namespace lldb_private; 19 20 // RegisterContextMemory constructor 21 RegisterContextMemory::RegisterContextMemory(Thread &thread, 22 uint32_t concrete_frame_idx, 23 DynamicRegisterInfo ®_infos, 24 addr_t reg_data_addr) 25 : RegisterContext(thread, concrete_frame_idx), m_reg_infos(reg_infos), 26 m_reg_valid(), m_reg_data(), m_reg_data_addr(reg_data_addr) { 27 // Resize our vector of bools to contain one bool for every register. We will 28 // use these boolean values to know when a register value is valid in 29 // m_reg_data. 30 const size_t num_regs = reg_infos.GetNumRegisters(); 31 assert(num_regs > 0); 32 m_reg_valid.resize(num_regs); 33 34 // Make a heap based buffer that is big enough to store all registers 35 DataBufferSP reg_data_sp( 36 new DataBufferHeap(reg_infos.GetRegisterDataByteSize(), 0)); 37 m_reg_data.SetData(reg_data_sp); 38 } 39 40 // Destructor 41 RegisterContextMemory::~RegisterContextMemory() = default; 42 43 void RegisterContextMemory::InvalidateAllRegisters() { 44 if (m_reg_data_addr != LLDB_INVALID_ADDRESS) 45 SetAllRegisterValid(false); 46 } 47 48 void RegisterContextMemory::SetAllRegisterValid(bool b) { 49 std::vector<bool>::iterator pos, end = m_reg_valid.end(); 50 for (pos = m_reg_valid.begin(); pos != end; ++pos) 51 *pos = b; 52 } 53 54 size_t RegisterContextMemory::GetRegisterCount() { 55 return m_reg_infos.GetNumRegisters(); 56 } 57 58 const RegisterInfo *RegisterContextMemory::GetRegisterInfoAtIndex(size_t reg) { 59 return m_reg_infos.GetRegisterInfoAtIndex(reg); 60 } 61 62 size_t RegisterContextMemory::GetRegisterSetCount() { 63 return m_reg_infos.GetNumRegisterSets(); 64 } 65 66 const RegisterSet *RegisterContextMemory::GetRegisterSet(size_t reg_set) { 67 return m_reg_infos.GetRegisterSet(reg_set); 68 } 69 70 uint32_t RegisterContextMemory::ConvertRegisterKindToRegisterNumber( 71 lldb::RegisterKind kind, uint32_t num) { 72 return m_reg_infos.ConvertRegisterKindToRegisterNumber(kind, num); 73 } 74 75 bool RegisterContextMemory::ReadRegister(const RegisterInfo *reg_info, 76 RegisterValue ®_value) { 77 const uint32_t reg_num = reg_info->kinds[eRegisterKindLLDB]; 78 if (!m_reg_valid[reg_num]) { 79 if (!ReadAllRegisterValues(m_reg_data.GetSharedDataBuffer())) 80 return false; 81 } 82 const bool partial_data_ok = false; 83 return reg_value 84 .SetValueFromData(reg_info, m_reg_data, reg_info->byte_offset, 85 partial_data_ok) 86 .Success(); 87 } 88 89 bool RegisterContextMemory::WriteRegister(const RegisterInfo *reg_info, 90 const RegisterValue ®_value) { 91 if (m_reg_data_addr != LLDB_INVALID_ADDRESS) { 92 const uint32_t reg_num = reg_info->kinds[eRegisterKindLLDB]; 93 addr_t reg_addr = m_reg_data_addr + reg_info->byte_offset; 94 Status error(WriteRegisterValueToMemory(reg_info, reg_addr, 95 reg_info->byte_size, reg_value)); 96 m_reg_valid[reg_num] = false; 97 return error.Success(); 98 } 99 return false; 100 } 101 102 bool RegisterContextMemory::ReadAllRegisterValues(DataBufferSP &data_sp) { 103 if (m_reg_data_addr != LLDB_INVALID_ADDRESS) { 104 ProcessSP process_sp(CalculateProcess()); 105 if (process_sp) { 106 Status error; 107 if (process_sp->ReadMemory(m_reg_data_addr, data_sp->GetBytes(), 108 data_sp->GetByteSize(), 109 error) == data_sp->GetByteSize()) { 110 SetAllRegisterValid(true); 111 return true; 112 } 113 } 114 } 115 return false; 116 } 117 118 bool RegisterContextMemory::WriteAllRegisterValues( 119 const DataBufferSP &data_sp) { 120 if (m_reg_data_addr != LLDB_INVALID_ADDRESS) { 121 ProcessSP process_sp(CalculateProcess()); 122 if (process_sp) { 123 Status error; 124 SetAllRegisterValid(false); 125 if (process_sp->WriteMemory(m_reg_data_addr, data_sp->GetBytes(), 126 data_sp->GetByteSize(), 127 error) == data_sp->GetByteSize()) 128 return true; 129 } 130 } 131 return false; 132 } 133 134 void RegisterContextMemory::SetAllRegisterData( 135 const lldb::DataBufferSP &data_sp) { 136 m_reg_data.SetData(data_sp); 137 SetAllRegisterValid(true); 138 } 139