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