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 &reg_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 &reg_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 &reg_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