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