15ffd83dbSDimitry Andric //===-- RegisterContextMemory.cpp -----------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "RegisterContextMemory.h"
100b57cec5SDimitry Andric 
110b57cec5SDimitry Andric #include "lldb/Target/Process.h"
120b57cec5SDimitry Andric #include "lldb/Target/Thread.h"
130b57cec5SDimitry Andric #include "lldb/Utility/DataBufferHeap.h"
140b57cec5SDimitry Andric #include "lldb/Utility/RegisterValue.h"
150b57cec5SDimitry Andric #include "lldb/Utility/Status.h"
160b57cec5SDimitry Andric 
170b57cec5SDimitry Andric using namespace lldb;
180b57cec5SDimitry Andric using namespace lldb_private;
190b57cec5SDimitry Andric 
200b57cec5SDimitry Andric // RegisterContextMemory constructor
RegisterContextMemory(Thread & thread,uint32_t concrete_frame_idx,DynamicRegisterInfo & reg_infos,addr_t reg_data_addr)210b57cec5SDimitry Andric RegisterContextMemory::RegisterContextMemory(Thread &thread,
220b57cec5SDimitry Andric                                              uint32_t concrete_frame_idx,
230b57cec5SDimitry Andric                                              DynamicRegisterInfo &reg_infos,
240b57cec5SDimitry Andric                                              addr_t reg_data_addr)
250b57cec5SDimitry Andric     : RegisterContext(thread, concrete_frame_idx), m_reg_infos(reg_infos),
260b57cec5SDimitry Andric       m_reg_valid(), m_reg_data(), m_reg_data_addr(reg_data_addr) {
270b57cec5SDimitry Andric   // Resize our vector of bools to contain one bool for every register. We will
280b57cec5SDimitry Andric   // use these boolean values to know when a register value is valid in
290b57cec5SDimitry Andric   // m_reg_data.
300b57cec5SDimitry Andric   const size_t num_regs = reg_infos.GetNumRegisters();
310b57cec5SDimitry Andric   assert(num_regs > 0);
320b57cec5SDimitry Andric   m_reg_valid.resize(num_regs);
330b57cec5SDimitry Andric 
340b57cec5SDimitry Andric   // Make a heap based buffer that is big enough to store all registers
3581ad6265SDimitry Andric   m_data =
3681ad6265SDimitry Andric       std::make_shared<DataBufferHeap>(reg_infos.GetRegisterDataByteSize(), 0);
3781ad6265SDimitry Andric   m_reg_data.SetData(m_data);
380b57cec5SDimitry Andric }
390b57cec5SDimitry Andric 
400b57cec5SDimitry Andric // Destructor
41fe6060f1SDimitry Andric RegisterContextMemory::~RegisterContextMemory() = default;
420b57cec5SDimitry Andric 
InvalidateAllRegisters()430b57cec5SDimitry Andric void RegisterContextMemory::InvalidateAllRegisters() {
440b57cec5SDimitry Andric   if (m_reg_data_addr != LLDB_INVALID_ADDRESS)
450b57cec5SDimitry Andric     SetAllRegisterValid(false);
460b57cec5SDimitry Andric }
470b57cec5SDimitry Andric 
SetAllRegisterValid(bool b)480b57cec5SDimitry Andric void RegisterContextMemory::SetAllRegisterValid(bool b) {
490b57cec5SDimitry Andric   std::vector<bool>::iterator pos, end = m_reg_valid.end();
500b57cec5SDimitry Andric   for (pos = m_reg_valid.begin(); pos != end; ++pos)
510b57cec5SDimitry Andric     *pos = b;
520b57cec5SDimitry Andric }
530b57cec5SDimitry Andric 
GetRegisterCount()540b57cec5SDimitry Andric size_t RegisterContextMemory::GetRegisterCount() {
550b57cec5SDimitry Andric   return m_reg_infos.GetNumRegisters();
560b57cec5SDimitry Andric }
570b57cec5SDimitry Andric 
GetRegisterInfoAtIndex(size_t reg)580b57cec5SDimitry Andric const RegisterInfo *RegisterContextMemory::GetRegisterInfoAtIndex(size_t reg) {
590b57cec5SDimitry Andric   return m_reg_infos.GetRegisterInfoAtIndex(reg);
600b57cec5SDimitry Andric }
610b57cec5SDimitry Andric 
GetRegisterSetCount()620b57cec5SDimitry Andric size_t RegisterContextMemory::GetRegisterSetCount() {
630b57cec5SDimitry Andric   return m_reg_infos.GetNumRegisterSets();
640b57cec5SDimitry Andric }
650b57cec5SDimitry Andric 
GetRegisterSet(size_t reg_set)660b57cec5SDimitry Andric const RegisterSet *RegisterContextMemory::GetRegisterSet(size_t reg_set) {
670b57cec5SDimitry Andric   return m_reg_infos.GetRegisterSet(reg_set);
680b57cec5SDimitry Andric }
690b57cec5SDimitry Andric 
ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind,uint32_t num)700b57cec5SDimitry Andric uint32_t RegisterContextMemory::ConvertRegisterKindToRegisterNumber(
710b57cec5SDimitry Andric     lldb::RegisterKind kind, uint32_t num) {
720b57cec5SDimitry Andric   return m_reg_infos.ConvertRegisterKindToRegisterNumber(kind, num);
730b57cec5SDimitry Andric }
740b57cec5SDimitry Andric 
ReadRegister(const RegisterInfo * reg_info,RegisterValue & reg_value)750b57cec5SDimitry Andric bool RegisterContextMemory::ReadRegister(const RegisterInfo *reg_info,
760b57cec5SDimitry Andric                                          RegisterValue &reg_value) {
770b57cec5SDimitry Andric   const uint32_t reg_num = reg_info->kinds[eRegisterKindLLDB];
780b57cec5SDimitry Andric   if (!m_reg_valid[reg_num]) {
7981ad6265SDimitry Andric     if (!ReadAllRegisterValues(m_data))
800b57cec5SDimitry Andric       return false;
810b57cec5SDimitry Andric   }
820b57cec5SDimitry Andric   const bool partial_data_ok = false;
830b57cec5SDimitry Andric   return reg_value
84bdd1243dSDimitry Andric       .SetValueFromData(*reg_info, m_reg_data, reg_info->byte_offset,
850b57cec5SDimitry Andric                         partial_data_ok)
860b57cec5SDimitry Andric       .Success();
870b57cec5SDimitry Andric }
880b57cec5SDimitry Andric 
WriteRegister(const RegisterInfo * reg_info,const RegisterValue & reg_value)890b57cec5SDimitry Andric bool RegisterContextMemory::WriteRegister(const RegisterInfo *reg_info,
900b57cec5SDimitry Andric                                           const RegisterValue &reg_value) {
910b57cec5SDimitry Andric   if (m_reg_data_addr != LLDB_INVALID_ADDRESS) {
920b57cec5SDimitry Andric     const uint32_t reg_num = reg_info->kinds[eRegisterKindLLDB];
930b57cec5SDimitry Andric     addr_t reg_addr = m_reg_data_addr + reg_info->byte_offset;
940b57cec5SDimitry Andric     Status error(WriteRegisterValueToMemory(reg_info, reg_addr,
950b57cec5SDimitry Andric                                             reg_info->byte_size, reg_value));
960b57cec5SDimitry Andric     m_reg_valid[reg_num] = false;
970b57cec5SDimitry Andric     return error.Success();
980b57cec5SDimitry Andric   }
990b57cec5SDimitry Andric   return false;
1000b57cec5SDimitry Andric }
1010b57cec5SDimitry Andric 
ReadAllRegisterValues(WritableDataBufferSP & data_sp)10281ad6265SDimitry Andric bool RegisterContextMemory::ReadAllRegisterValues(
10381ad6265SDimitry Andric     WritableDataBufferSP &data_sp) {
1040b57cec5SDimitry Andric   if (m_reg_data_addr != LLDB_INVALID_ADDRESS) {
1050b57cec5SDimitry Andric     ProcessSP process_sp(CalculateProcess());
1060b57cec5SDimitry Andric     if (process_sp) {
1070b57cec5SDimitry Andric       Status error;
1080b57cec5SDimitry Andric       if (process_sp->ReadMemory(m_reg_data_addr, data_sp->GetBytes(),
1090b57cec5SDimitry Andric                                  data_sp->GetByteSize(),
1100b57cec5SDimitry Andric                                  error) == data_sp->GetByteSize()) {
1110b57cec5SDimitry Andric         SetAllRegisterValid(true);
1120b57cec5SDimitry Andric         return true;
1130b57cec5SDimitry Andric       }
1140b57cec5SDimitry Andric     }
1150b57cec5SDimitry Andric   }
1160b57cec5SDimitry Andric   return false;
1170b57cec5SDimitry Andric }
1180b57cec5SDimitry Andric 
WriteAllRegisterValues(const DataBufferSP & data_sp)1190b57cec5SDimitry Andric bool RegisterContextMemory::WriteAllRegisterValues(
1200b57cec5SDimitry Andric     const DataBufferSP &data_sp) {
1210b57cec5SDimitry Andric   if (m_reg_data_addr != LLDB_INVALID_ADDRESS) {
1220b57cec5SDimitry Andric     ProcessSP process_sp(CalculateProcess());
1230b57cec5SDimitry Andric     if (process_sp) {
1240b57cec5SDimitry Andric       Status error;
1250b57cec5SDimitry Andric       SetAllRegisterValid(false);
1260b57cec5SDimitry Andric       if (process_sp->WriteMemory(m_reg_data_addr, data_sp->GetBytes(),
1270b57cec5SDimitry Andric                                   data_sp->GetByteSize(),
1280b57cec5SDimitry Andric                                   error) == data_sp->GetByteSize())
1290b57cec5SDimitry Andric         return true;
1300b57cec5SDimitry Andric     }
1310b57cec5SDimitry Andric   }
1320b57cec5SDimitry Andric   return false;
1330b57cec5SDimitry Andric }
1340b57cec5SDimitry Andric 
SetAllRegisterData(const lldb::DataBufferSP & data_sp)1350b57cec5SDimitry Andric void RegisterContextMemory::SetAllRegisterData(
1360b57cec5SDimitry Andric     const lldb::DataBufferSP &data_sp) {
1370b57cec5SDimitry Andric   m_reg_data.SetData(data_sp);
1380b57cec5SDimitry Andric   SetAllRegisterValid(true);
1390b57cec5SDimitry Andric }
140