xref: /src/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextMemory.cpp (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
1cfca06d7SDimitry Andric //===-- RegisterContextMemory.cpp -----------------------------------------===//
2f034231aSEd Maste //
35f29bb8aSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45f29bb8aSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
55f29bb8aSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6f034231aSEd Maste //
7f034231aSEd Maste //===----------------------------------------------------------------------===//
8f034231aSEd Maste 
9f034231aSEd Maste #include "RegisterContextMemory.h"
10f034231aSEd Maste 
11f034231aSEd Maste #include "lldb/Target/Process.h"
12f034231aSEd Maste #include "lldb/Target/Thread.h"
1374a628f7SDimitry Andric #include "lldb/Utility/DataBufferHeap.h"
1494994d37SDimitry Andric #include "lldb/Utility/RegisterValue.h"
15b76161e4SDimitry Andric #include "lldb/Utility/Status.h"
16f034231aSEd Maste 
17f034231aSEd Maste using namespace lldb;
18f034231aSEd Maste using namespace lldb_private;
19f034231aSEd Maste 
20f034231aSEd Maste // RegisterContextMemory constructor
RegisterContextMemory(Thread & thread,uint32_t concrete_frame_idx,DynamicRegisterInfo & reg_infos,addr_t reg_data_addr)2114f1b3e8SDimitry Andric RegisterContextMemory::RegisterContextMemory(Thread &thread,
22f034231aSEd Maste                                              uint32_t concrete_frame_idx,
23f034231aSEd Maste                                              DynamicRegisterInfo &reg_infos,
2414f1b3e8SDimitry Andric                                              addr_t reg_data_addr)
2514f1b3e8SDimitry Andric     : RegisterContext(thread, concrete_frame_idx), m_reg_infos(reg_infos),
2614f1b3e8SDimitry Andric       m_reg_valid(), m_reg_data(), m_reg_data_addr(reg_data_addr) {
27f73363f1SDimitry Andric   // Resize our vector of bools to contain one bool for every register. We will
28f73363f1SDimitry Andric   // use these boolean values to know when a register value is valid in
29f73363f1SDimitry Andric   // m_reg_data.
30f034231aSEd Maste   const size_t num_regs = reg_infos.GetNumRegisters();
31f034231aSEd Maste   assert(num_regs > 0);
32f034231aSEd Maste   m_reg_valid.resize(num_regs);
33f034231aSEd Maste 
34f034231aSEd Maste   // Make a heap based buffer that is big enough to store all registers
35145449b1SDimitry Andric   m_data =
36145449b1SDimitry Andric       std::make_shared<DataBufferHeap>(reg_infos.GetRegisterDataByteSize(), 0);
37145449b1SDimitry Andric   m_reg_data.SetData(m_data);
38f034231aSEd Maste }
39f034231aSEd Maste 
40f034231aSEd Maste // Destructor
41344a3780SDimitry Andric RegisterContextMemory::~RegisterContextMemory() = default;
42f034231aSEd Maste 
InvalidateAllRegisters()4314f1b3e8SDimitry Andric void RegisterContextMemory::InvalidateAllRegisters() {
44f034231aSEd Maste   if (m_reg_data_addr != LLDB_INVALID_ADDRESS)
45f034231aSEd Maste     SetAllRegisterValid(false);
46f034231aSEd Maste }
47f034231aSEd Maste 
SetAllRegisterValid(bool b)4814f1b3e8SDimitry Andric void RegisterContextMemory::SetAllRegisterValid(bool b) {
49f034231aSEd Maste   std::vector<bool>::iterator pos, end = m_reg_valid.end();
50f034231aSEd Maste   for (pos = m_reg_valid.begin(); pos != end; ++pos)
51f034231aSEd Maste     *pos = b;
52f034231aSEd Maste }
53f034231aSEd Maste 
GetRegisterCount()5414f1b3e8SDimitry Andric size_t RegisterContextMemory::GetRegisterCount() {
55f034231aSEd Maste   return m_reg_infos.GetNumRegisters();
56f034231aSEd Maste }
57f034231aSEd Maste 
GetRegisterInfoAtIndex(size_t reg)5814f1b3e8SDimitry Andric const RegisterInfo *RegisterContextMemory::GetRegisterInfoAtIndex(size_t reg) {
59f034231aSEd Maste   return m_reg_infos.GetRegisterInfoAtIndex(reg);
60f034231aSEd Maste }
61f034231aSEd Maste 
GetRegisterSetCount()6214f1b3e8SDimitry Andric size_t RegisterContextMemory::GetRegisterSetCount() {
63f034231aSEd Maste   return m_reg_infos.GetNumRegisterSets();
64f034231aSEd Maste }
65f034231aSEd Maste 
GetRegisterSet(size_t reg_set)6614f1b3e8SDimitry Andric const RegisterSet *RegisterContextMemory::GetRegisterSet(size_t reg_set) {
67f034231aSEd Maste   return m_reg_infos.GetRegisterSet(reg_set);
68f034231aSEd Maste }
69f034231aSEd Maste 
ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind,uint32_t num)7014f1b3e8SDimitry Andric uint32_t RegisterContextMemory::ConvertRegisterKindToRegisterNumber(
7114f1b3e8SDimitry Andric     lldb::RegisterKind kind, uint32_t num) {
72f034231aSEd Maste   return m_reg_infos.ConvertRegisterKindToRegisterNumber(kind, num);
73f034231aSEd Maste }
74f034231aSEd Maste 
ReadRegister(const RegisterInfo * reg_info,RegisterValue & reg_value)7514f1b3e8SDimitry Andric bool RegisterContextMemory::ReadRegister(const RegisterInfo *reg_info,
7614f1b3e8SDimitry Andric                                          RegisterValue &reg_value) {
77f034231aSEd Maste   const uint32_t reg_num = reg_info->kinds[eRegisterKindLLDB];
7814f1b3e8SDimitry Andric   if (!m_reg_valid[reg_num]) {
79145449b1SDimitry Andric     if (!ReadAllRegisterValues(m_data))
80f034231aSEd Maste       return false;
81f034231aSEd Maste   }
82f034231aSEd Maste   const bool partial_data_ok = false;
8314f1b3e8SDimitry Andric   return reg_value
84e3b55780SDimitry Andric       .SetValueFromData(*reg_info, m_reg_data, reg_info->byte_offset,
8514f1b3e8SDimitry Andric                         partial_data_ok)
8614f1b3e8SDimitry Andric       .Success();
87f034231aSEd Maste }
88f034231aSEd Maste 
WriteRegister(const RegisterInfo * reg_info,const RegisterValue & reg_value)8914f1b3e8SDimitry Andric bool RegisterContextMemory::WriteRegister(const RegisterInfo *reg_info,
9014f1b3e8SDimitry Andric                                           const RegisterValue &reg_value) {
9114f1b3e8SDimitry Andric   if (m_reg_data_addr != LLDB_INVALID_ADDRESS) {
92f034231aSEd Maste     const uint32_t reg_num = reg_info->kinds[eRegisterKindLLDB];
93f034231aSEd Maste     addr_t reg_addr = m_reg_data_addr + reg_info->byte_offset;
94b76161e4SDimitry Andric     Status error(WriteRegisterValueToMemory(reg_info, reg_addr,
9514f1b3e8SDimitry Andric                                             reg_info->byte_size, reg_value));
96f034231aSEd Maste     m_reg_valid[reg_num] = false;
97f034231aSEd Maste     return error.Success();
98f034231aSEd Maste   }
99f034231aSEd Maste   return false;
100f034231aSEd Maste }
101f034231aSEd Maste 
ReadAllRegisterValues(WritableDataBufferSP & data_sp)102145449b1SDimitry Andric bool RegisterContextMemory::ReadAllRegisterValues(
103145449b1SDimitry Andric     WritableDataBufferSP &data_sp) {
10414f1b3e8SDimitry Andric   if (m_reg_data_addr != LLDB_INVALID_ADDRESS) {
105f034231aSEd Maste     ProcessSP process_sp(CalculateProcess());
10614f1b3e8SDimitry Andric     if (process_sp) {
107b76161e4SDimitry Andric       Status error;
10814f1b3e8SDimitry Andric       if (process_sp->ReadMemory(m_reg_data_addr, data_sp->GetBytes(),
10914f1b3e8SDimitry Andric                                  data_sp->GetByteSize(),
11014f1b3e8SDimitry Andric                                  error) == data_sp->GetByteSize()) {
111f034231aSEd Maste         SetAllRegisterValid(true);
112f034231aSEd Maste         return true;
113f034231aSEd Maste       }
114f034231aSEd Maste     }
115f034231aSEd Maste   }
116f034231aSEd Maste   return false;
117f034231aSEd Maste }
118f034231aSEd Maste 
WriteAllRegisterValues(const DataBufferSP & data_sp)11914f1b3e8SDimitry Andric bool RegisterContextMemory::WriteAllRegisterValues(
12014f1b3e8SDimitry Andric     const DataBufferSP &data_sp) {
12114f1b3e8SDimitry Andric   if (m_reg_data_addr != LLDB_INVALID_ADDRESS) {
122f034231aSEd Maste     ProcessSP process_sp(CalculateProcess());
12314f1b3e8SDimitry Andric     if (process_sp) {
124b76161e4SDimitry Andric       Status error;
125f034231aSEd Maste       SetAllRegisterValid(false);
12614f1b3e8SDimitry Andric       if (process_sp->WriteMemory(m_reg_data_addr, data_sp->GetBytes(),
12714f1b3e8SDimitry Andric                                   data_sp->GetByteSize(),
12814f1b3e8SDimitry Andric                                   error) == data_sp->GetByteSize())
129f034231aSEd Maste         return true;
130f034231aSEd Maste     }
131f034231aSEd Maste   }
132f034231aSEd Maste   return false;
133f034231aSEd Maste }
134f034231aSEd Maste 
SetAllRegisterData(const lldb::DataBufferSP & data_sp)13514f1b3e8SDimitry Andric void RegisterContextMemory::SetAllRegisterData(
13614f1b3e8SDimitry Andric     const lldb::DataBufferSP &data_sp) {
137f034231aSEd Maste   m_reg_data.SetData(data_sp);
138f034231aSEd Maste   SetAllRegisterValid(true);
139f034231aSEd Maste }
140