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
RegisterContextMemory(Thread & thread,uint32_t concrete_frame_idx,DynamicRegisterInfo & reg_infos,addr_t reg_data_addr)21 RegisterContextMemory::RegisterContextMemory(Thread &thread,
22                                              uint32_t concrete_frame_idx,
23                                              DynamicRegisterInfo &reg_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   m_data =
36       std::make_shared<DataBufferHeap>(reg_infos.GetRegisterDataByteSize(), 0);
37   m_reg_data.SetData(m_data);
38 }
39 
40 // Destructor
41 RegisterContextMemory::~RegisterContextMemory() = default;
42 
InvalidateAllRegisters()43 void RegisterContextMemory::InvalidateAllRegisters() {
44   if (m_reg_data_addr != LLDB_INVALID_ADDRESS)
45     SetAllRegisterValid(false);
46 }
47 
SetAllRegisterValid(bool b)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 
GetRegisterCount()54 size_t RegisterContextMemory::GetRegisterCount() {
55   return m_reg_infos.GetNumRegisters();
56 }
57 
GetRegisterInfoAtIndex(size_t reg)58 const RegisterInfo *RegisterContextMemory::GetRegisterInfoAtIndex(size_t reg) {
59   return m_reg_infos.GetRegisterInfoAtIndex(reg);
60 }
61 
GetRegisterSetCount()62 size_t RegisterContextMemory::GetRegisterSetCount() {
63   return m_reg_infos.GetNumRegisterSets();
64 }
65 
GetRegisterSet(size_t reg_set)66 const RegisterSet *RegisterContextMemory::GetRegisterSet(size_t reg_set) {
67   return m_reg_infos.GetRegisterSet(reg_set);
68 }
69 
ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind,uint32_t num)70 uint32_t RegisterContextMemory::ConvertRegisterKindToRegisterNumber(
71     lldb::RegisterKind kind, uint32_t num) {
72   return m_reg_infos.ConvertRegisterKindToRegisterNumber(kind, num);
73 }
74 
ReadRegister(const RegisterInfo * reg_info,RegisterValue & reg_value)75 bool RegisterContextMemory::ReadRegister(const RegisterInfo *reg_info,
76                                          RegisterValue &reg_value) {
77   const uint32_t reg_num = reg_info->kinds[eRegisterKindLLDB];
78   if (!m_reg_valid[reg_num]) {
79     if (!ReadAllRegisterValues(m_data))
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 
WriteRegister(const RegisterInfo * reg_info,const RegisterValue & reg_value)89 bool RegisterContextMemory::WriteRegister(const RegisterInfo *reg_info,
90                                           const RegisterValue &reg_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 
ReadAllRegisterValues(WritableDataBufferSP & data_sp)102 bool RegisterContextMemory::ReadAllRegisterValues(
103     WritableDataBufferSP &data_sp) {
104   if (m_reg_data_addr != LLDB_INVALID_ADDRESS) {
105     ProcessSP process_sp(CalculateProcess());
106     if (process_sp) {
107       Status error;
108       if (process_sp->ReadMemory(m_reg_data_addr, data_sp->GetBytes(),
109                                  data_sp->GetByteSize(),
110                                  error) == data_sp->GetByteSize()) {
111         SetAllRegisterValid(true);
112         return true;
113       }
114     }
115   }
116   return false;
117 }
118 
WriteAllRegisterValues(const DataBufferSP & data_sp)119 bool RegisterContextMemory::WriteAllRegisterValues(
120     const DataBufferSP &data_sp) {
121   if (m_reg_data_addr != LLDB_INVALID_ADDRESS) {
122     ProcessSP process_sp(CalculateProcess());
123     if (process_sp) {
124       Status error;
125       SetAllRegisterValid(false);
126       if (process_sp->WriteMemory(m_reg_data_addr, data_sp->GetBytes(),
127                                   data_sp->GetByteSize(),
128                                   error) == data_sp->GetByteSize())
129         return true;
130     }
131   }
132   return false;
133 }
134 
SetAllRegisterData(const lldb::DataBufferSP & data_sp)135 void RegisterContextMemory::SetAllRegisterData(
136     const lldb::DataBufferSP &data_sp) {
137   m_reg_data.SetData(data_sp);
138   SetAllRegisterValid(true);
139 }
140