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 // RegisterContextMemory constructor
22 RegisterContextMemory::RegisterContextMemory(Thread &thread,
23                                              uint32_t concrete_frame_idx,
24                                              DynamicRegisterInfo &reg_infos,
25                                              addr_t reg_data_addr)
26     : RegisterContext(thread, concrete_frame_idx), m_reg_infos(reg_infos),
27       m_reg_valid(), m_reg_data(), m_reg_data_addr(reg_data_addr) {
28   // Resize our vector of bools to contain one bool for every register. We will
29   // use these boolean values to know when a register value is valid in
30   // m_reg_data.
31   const size_t num_regs = reg_infos.GetNumRegisters();
32   assert(num_regs > 0);
33   m_reg_valid.resize(num_regs);
34 
35   // Make a heap based buffer that is big enough to store all registers
36   DataBufferSP reg_data_sp(
37       new DataBufferHeap(reg_infos.GetRegisterDataByteSize(), 0));
38   m_reg_data.SetData(reg_data_sp);
39 }
40 
41 // Destructor
42 RegisterContextMemory::~RegisterContextMemory() {}
43 
44 void RegisterContextMemory::InvalidateAllRegisters() {
45   if (m_reg_data_addr != LLDB_INVALID_ADDRESS)
46     SetAllRegisterValid(false);
47 }
48 
49 void RegisterContextMemory::SetAllRegisterValid(bool b) {
50   std::vector<bool>::iterator pos, end = m_reg_valid.end();
51   for (pos = m_reg_valid.begin(); pos != end; ++pos)
52     *pos = b;
53 }
54 
55 size_t RegisterContextMemory::GetRegisterCount() {
56   return m_reg_infos.GetNumRegisters();
57 }
58 
59 const RegisterInfo *RegisterContextMemory::GetRegisterInfoAtIndex(size_t reg) {
60   return m_reg_infos.GetRegisterInfoAtIndex(reg);
61 }
62 
63 size_t RegisterContextMemory::GetRegisterSetCount() {
64   return m_reg_infos.GetNumRegisterSets();
65 }
66 
67 const RegisterSet *RegisterContextMemory::GetRegisterSet(size_t reg_set) {
68   return m_reg_infos.GetRegisterSet(reg_set);
69 }
70 
71 uint32_t RegisterContextMemory::ConvertRegisterKindToRegisterNumber(
72     lldb::RegisterKind kind, uint32_t num) {
73   return m_reg_infos.ConvertRegisterKindToRegisterNumber(kind, num);
74 }
75 
76 bool RegisterContextMemory::ReadRegister(const RegisterInfo *reg_info,
77                                          RegisterValue &reg_value) {
78   const uint32_t reg_num = reg_info->kinds[eRegisterKindLLDB];
79   if (!m_reg_valid[reg_num]) {
80     if (!ReadAllRegisterValues(m_reg_data.GetSharedDataBuffer()))
81       return false;
82   }
83   const bool partial_data_ok = false;
84   return reg_value
85       .SetValueFromData(reg_info, m_reg_data, reg_info->byte_offset,
86                         partial_data_ok)
87       .Success();
88 }
89 
90 bool RegisterContextMemory::WriteRegister(const RegisterInfo *reg_info,
91                                           const RegisterValue &reg_value) {
92   if (m_reg_data_addr != LLDB_INVALID_ADDRESS) {
93     const uint32_t reg_num = reg_info->kinds[eRegisterKindLLDB];
94     addr_t reg_addr = m_reg_data_addr + reg_info->byte_offset;
95     Status error(WriteRegisterValueToMemory(reg_info, reg_addr,
96                                             reg_info->byte_size, reg_value));
97     m_reg_valid[reg_num] = false;
98     return error.Success();
99   }
100   return false;
101 }
102 
103 bool RegisterContextMemory::ReadAllRegisterValues(DataBufferSP &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 
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 
135 void RegisterContextMemory::SetAllRegisterData(
136     const lldb::DataBufferSP &data_sp) {
137   m_reg_data.SetData(data_sp);
138   SetAllRegisterValid(true);
139 }
140